
<!DOCTYPE html>

<html>
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>pymatgen.transformations.advanced_transformations &#8212; pymatgen 2020.7.3 documentation</title>
    <link rel="stylesheet" href="../../../_static/basic.css" type="text/css" />
    <link rel="stylesheet" href="../../../_static/pygments.css" type="text/css" />
    <script id="documentation_options" data-url_root="../../../" src="../../../_static/documentation_options.js"></script>
    <script src="../../../_static/jquery.js"></script>
    <script src="../../../_static/underscore.js"></script>
    <script src="../../../_static/doctools.js"></script>
    <script src="../../../_static/language_data.js"></script>
    <script async="async" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.7/latest.js?config=TeX-AMS-MML_HTMLorMML"></script>
    <link rel="index" title="Index" href="../../../genindex.html" />
    <link rel="search" title="Search" href="../../../search.html" />
 
<script type="text/javascript">
  var _gaq = _gaq || [];
  _gaq.push(['_setAccount', 'UA-33990148-1']);
  _gaq.push(['_trackPageview']);
</script>

  </head><body>
    <div class="related" role="navigation" aria-label="related navigation">
      <h3>Navigation</h3>
      <ul>
        <li class="right" style="margin-right: 10px">
          <a href="../../../genindex.html" title="General Index"
             accesskey="I">index</a></li>
        <li class="right" >
          <a href="../../../py-modindex.html" title="Python Module Index"
             >modules</a> |</li>
        <li class="nav-item nav-item-0"><a href="../../../index.html">pymatgen 2020.7.3 documentation</a> &#187;</li>
          <li class="nav-item nav-item-1"><a href="../../index.html" >Module code</a> &#187;</li>
          <li class="nav-item nav-item-2"><a href="../../pymatgen.html" accesskey="U">pymatgen</a> &#187;</li>
        <li class="nav-item nav-item-this"><a href="">pymatgen.transformations.advanced_transformations</a></li> 
      </ul>
    </div>  

    <div class="document">
      <div class="documentwrapper">
          <div class="body" role="main">
            
  <h1>Source code for pymatgen.transformations.advanced_transformations</h1><div class="highlight"><pre>
<span></span><span class="c1"># coding: utf-8</span>
<span class="c1"># Copyright (c) Pymatgen Development Team.</span>
<span class="c1"># Distributed under the terms of the MIT License.</span>

<span class="sd">&quot;&quot;&quot;</span>
<span class="sd">This module implements more advanced transformations.</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="kn">from</span> <span class="nn">typing</span> <span class="kn">import</span> <span class="n">Optional</span><span class="p">,</span> <span class="n">Dict</span>

<span class="kn">import</span> <span class="nn">numpy</span> <span class="k">as</span> <span class="nn">np</span>
<span class="kn">from</span> <span class="nn">fractions</span> <span class="kn">import</span> <span class="n">Fraction</span>
<span class="kn">from</span> <span class="nn">math</span> <span class="kn">import</span> <span class="n">gcd</span>
<span class="kn">from</span> <span class="nn">itertools</span> <span class="kn">import</span> <span class="n">groupby</span><span class="p">,</span> <span class="n">product</span>
<span class="kn">from</span> <span class="nn">string</span> <span class="kn">import</span> <span class="n">ascii_lowercase</span>
<span class="kn">from</span> <span class="nn">warnings</span> <span class="kn">import</span> <span class="n">warn</span>
<span class="kn">import</span> <span class="nn">logging</span>
<span class="kn">import</span> <span class="nn">math</span>

<span class="kn">import</span> <span class="nn">warnings</span>

<span class="kn">from</span> <span class="nn">monty.dev</span> <span class="kn">import</span> <span class="n">requires</span>
<span class="kn">from</span> <span class="nn">monty.fractions</span> <span class="kn">import</span> <span class="n">lcm</span>
<span class="kn">from</span> <span class="nn">monty.json</span> <span class="kn">import</span> <span class="n">MSONable</span>

<span class="kn">from</span> <span class="nn">pymatgen.core.periodic_table</span> <span class="kn">import</span> <span class="n">Element</span><span class="p">,</span> <span class="n">Specie</span><span class="p">,</span> <span class="n">get_el_sp</span><span class="p">,</span> <span class="n">DummySpecie</span>
<span class="kn">from</span> <span class="nn">pymatgen.io.ase</span> <span class="kn">import</span> <span class="n">AseAtomsAdaptor</span>
<span class="kn">from</span> <span class="nn">pymatgen.transformations.transformation_abc</span> <span class="kn">import</span> <span class="n">AbstractTransformation</span>
<span class="kn">from</span> <span class="nn">pymatgen.transformations.standard_transformations</span> <span class="kn">import</span> <span class="p">(</span>
    <span class="n">SubstitutionTransformation</span><span class="p">,</span>
    <span class="n">OrderDisorderedStructureTransformation</span><span class="p">,</span>
    <span class="n">SupercellTransformation</span><span class="p">,</span>
<span class="p">)</span>
<span class="kn">from</span> <span class="nn">pymatgen.command_line.enumlib_caller</span> <span class="kn">import</span> <span class="n">EnumlibAdaptor</span><span class="p">,</span> <span class="n">EnumError</span>
<span class="kn">from</span> <span class="nn">pymatgen.analysis.ewald</span> <span class="kn">import</span> <span class="n">EwaldSummation</span>
<span class="kn">from</span> <span class="nn">pymatgen.core.structure</span> <span class="kn">import</span> <span class="n">Structure</span>
<span class="kn">from</span> <span class="nn">pymatgen.symmetry.analyzer</span> <span class="kn">import</span> <span class="n">SpacegroupAnalyzer</span>
<span class="kn">from</span> <span class="nn">pymatgen.analysis.structure_prediction.substitution_probability</span> <span class="kn">import</span> <span class="p">(</span>
    <span class="n">SubstitutionPredictor</span><span class="p">,</span>
<span class="p">)</span>
<span class="kn">from</span> <span class="nn">pymatgen.analysis.structure_matcher</span> <span class="kn">import</span> <span class="n">StructureMatcher</span><span class="p">,</span> <span class="n">SpinComparator</span>
<span class="kn">from</span> <span class="nn">pymatgen.analysis.energy_models</span> <span class="kn">import</span> <span class="n">SymmetryModel</span>
<span class="kn">from</span> <span class="nn">pymatgen.analysis.bond_valence</span> <span class="kn">import</span> <span class="n">BVAnalyzer</span>
<span class="kn">from</span> <span class="nn">pymatgen.core.surface</span> <span class="kn">import</span> <span class="n">SlabGenerator</span>
<span class="kn">from</span> <span class="nn">pymatgen.electronic_structure.core</span> <span class="kn">import</span> <span class="n">Spin</span>
<span class="kn">from</span> <span class="nn">pymatgen.analysis.gb.grain</span> <span class="kn">import</span> <span class="n">GrainBoundaryGenerator</span>
<span class="kn">from</span> <span class="nn">pymatgen.analysis.adsorption</span> <span class="kn">import</span> <span class="n">AdsorbateSiteFinder</span>
<span class="kn">from</span> <span class="nn">pymatgen.command_line.mcsqs_caller</span> <span class="kn">import</span> <span class="n">run_mcsqs</span>
<span class="kn">from</span> <span class="nn">pymatgen.analysis.local_env</span> <span class="kn">import</span> <span class="n">MinimumDistanceNN</span>

<span class="k">try</span><span class="p">:</span>
    <span class="kn">import</span> <span class="nn">hiphive</span>  <span class="c1"># type: ignore</span>
<span class="k">except</span> <span class="ne">ImportError</span><span class="p">:</span>
    <span class="n">hiphive</span> <span class="o">=</span> <span class="kc">None</span>

<span class="n">__author__</span> <span class="o">=</span> <span class="p">(</span>
    <span class="s2">&quot;Shyue Ping Ong, Stephen Dacek, Anubhav Jain, Matthew Horton, &quot;</span> <span class="s2">&quot;Alex Ganose&quot;</span>
<span class="p">)</span>
<span class="n">__copyright__</span> <span class="o">=</span> <span class="s2">&quot;Copyright 2012, The Materials Project&quot;</span>
<span class="n">__version__</span> <span class="o">=</span> <span class="s2">&quot;1.0&quot;</span>
<span class="n">__maintainer__</span> <span class="o">=</span> <span class="s2">&quot;Shyue Ping Ong&quot;</span>
<span class="n">__email__</span> <span class="o">=</span> <span class="s2">&quot;shyuep@gmail.com&quot;</span>
<span class="n">__date__</span> <span class="o">=</span> <span class="s2">&quot;Jul 24, 2012&quot;</span>

<span class="n">logger</span> <span class="o">=</span> <span class="n">logging</span><span class="o">.</span><span class="n">getLogger</span><span class="p">(</span><span class="vm">__name__</span><span class="p">)</span>


<div class="viewcode-block" id="ChargeBalanceTransformation"><a class="viewcode-back" href="../../../pymatgen.transformations.advanced_transformations.html#pymatgen.transformations.advanced_transformations.ChargeBalanceTransformation">[docs]</a><span class="k">class</span> <span class="nc">ChargeBalanceTransformation</span><span class="p">(</span><span class="n">AbstractTransformation</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    This is a transformation that disorders a structure to make it charge</span>
<span class="sd">    balanced, given an oxidation state-decorated structure.</span>
<span class="sd">    &quot;&quot;&quot;</span>

    <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">charge_balance_sp</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Args:</span>
<span class="sd">            charge_balance_sp: specie to add or remove. Currently only removal</span>
<span class="sd">                is supported</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">charge_balance_sp</span> <span class="o">=</span> <span class="nb">str</span><span class="p">(</span><span class="n">charge_balance_sp</span><span class="p">)</span>

<div class="viewcode-block" id="ChargeBalanceTransformation.apply_transformation"><a class="viewcode-back" href="../../../pymatgen.transformations.advanced_transformations.html#pymatgen.transformations.advanced_transformations.ChargeBalanceTransformation.apply_transformation">[docs]</a>    <span class="k">def</span> <span class="nf">apply_transformation</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">structure</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Applies the transformation.</span>

<span class="sd">        Args:</span>
<span class="sd">            structure: Input Structure</span>

<span class="sd">        Returns:</span>
<span class="sd">            Charge balanced structure.</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="n">charge</span> <span class="o">=</span> <span class="n">structure</span><span class="o">.</span><span class="n">charge</span>
        <span class="n">specie</span> <span class="o">=</span> <span class="n">get_el_sp</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">charge_balance_sp</span><span class="p">)</span>
        <span class="n">num_to_remove</span> <span class="o">=</span> <span class="n">charge</span> <span class="o">/</span> <span class="n">specie</span><span class="o">.</span><span class="n">oxi_state</span>
        <span class="n">num_in_structure</span> <span class="o">=</span> <span class="n">structure</span><span class="o">.</span><span class="n">composition</span><span class="p">[</span><span class="n">specie</span><span class="p">]</span>
        <span class="n">removal_fraction</span> <span class="o">=</span> <span class="n">num_to_remove</span> <span class="o">/</span> <span class="n">num_in_structure</span>
        <span class="k">if</span> <span class="n">removal_fraction</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">:</span>
            <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span>
                <span class="s2">&quot;addition of specie not yet supported by &quot;</span> <span class="s2">&quot;ChargeBalanceTransformation&quot;</span>
            <span class="p">)</span>
        <span class="n">trans</span> <span class="o">=</span> <span class="n">SubstitutionTransformation</span><span class="p">(</span>
            <span class="p">{</span><span class="bp">self</span><span class="o">.</span><span class="n">charge_balance_sp</span><span class="p">:</span> <span class="p">{</span><span class="bp">self</span><span class="o">.</span><span class="n">charge_balance_sp</span><span class="p">:</span> <span class="mi">1</span> <span class="o">-</span> <span class="n">removal_fraction</span><span class="p">}}</span>
        <span class="p">)</span>
        <span class="k">return</span> <span class="n">trans</span><span class="o">.</span><span class="n">apply_transformation</span><span class="p">(</span><span class="n">structure</span><span class="p">)</span></div>

    <span class="k">def</span> <span class="fm">__str__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="k">return</span> <span class="s2">&quot;Charge Balance Transformation : &quot;</span> <span class="o">+</span> <span class="s2">&quot;Species to remove = </span><span class="si">{}</span><span class="s2">&quot;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span>
            <span class="nb">str</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">charge_balance_sp</span><span class="p">)</span>
        <span class="p">)</span>

    <span class="k">def</span> <span class="fm">__repr__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="fm">__str__</span><span class="p">()</span>

    <span class="nd">@property</span>
    <span class="k">def</span> <span class="nf">inverse</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;Returns: None&quot;&quot;&quot;</span>
        <span class="k">return</span> <span class="kc">None</span>

    <span class="nd">@property</span>
    <span class="k">def</span> <span class="nf">is_one_to_many</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;Returns: False&quot;&quot;&quot;</span>
        <span class="k">return</span> <span class="kc">False</span></div>


<div class="viewcode-block" id="SuperTransformation"><a class="viewcode-back" href="../../../pymatgen.transformations.advanced_transformations.html#pymatgen.transformations.advanced_transformations.SuperTransformation">[docs]</a><span class="k">class</span> <span class="nc">SuperTransformation</span><span class="p">(</span><span class="n">AbstractTransformation</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    This is a transformation that is inherently one-to-many. It is constructed</span>
<span class="sd">    from a list of transformations and returns one structure for each</span>
<span class="sd">    transformation. The primary use for this class is extending a transmuter</span>
<span class="sd">    object.</span>
<span class="sd">    &quot;&quot;&quot;</span>

    <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">transformations</span><span class="p">,</span> <span class="n">nstructures_per_trans</span><span class="o">=</span><span class="mi">1</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Args:</span>
<span class="sd">            transformations ([transformations]): List of transformations to apply</span>
<span class="sd">                to a structure. One transformation is applied to each output</span>
<span class="sd">                structure.</span>
<span class="sd">            nstructures_per_trans (int): If the transformations are one-to-many and,</span>
<span class="sd">                nstructures_per_trans structures from each transformation are</span>
<span class="sd">                added to the full list. Defaults to 1, i.e., only best structure.</span>
<span class="sd">        &quot;&quot;&quot;</span>

        <span class="bp">self</span><span class="o">.</span><span class="n">_transformations</span> <span class="o">=</span> <span class="n">transformations</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">nstructures_per_trans</span> <span class="o">=</span> <span class="n">nstructures_per_trans</span>

<div class="viewcode-block" id="SuperTransformation.apply_transformation"><a class="viewcode-back" href="../../../pymatgen.transformations.advanced_transformations.html#pymatgen.transformations.advanced_transformations.SuperTransformation.apply_transformation">[docs]</a>    <span class="k">def</span> <span class="nf">apply_transformation</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">structure</span><span class="p">,</span> <span class="n">return_ranked_list</span><span class="o">=</span><span class="kc">False</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Applies the transformation.</span>

<span class="sd">        Args:</span>
<span class="sd">            structure: Input Structure</span>
<span class="sd">            return_ranked_list: Number of structures to return.</span>

<span class="sd">        Returns:</span>
<span class="sd">            Structures with all transformations applied.</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="k">if</span> <span class="ow">not</span> <span class="n">return_ranked_list</span><span class="p">:</span>
            <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span>
                <span class="s2">&quot;SuperTransformation has no single best structure&quot;</span>
                <span class="s2">&quot; output. Must use return_ranked_list&quot;</span>
            <span class="p">)</span>
        <span class="n">structures</span> <span class="o">=</span> <span class="p">[]</span>
        <span class="k">for</span> <span class="n">t</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">_transformations</span><span class="p">:</span>
            <span class="k">if</span> <span class="n">t</span><span class="o">.</span><span class="n">is_one_to_many</span><span class="p">:</span>
                <span class="k">for</span> <span class="n">d</span> <span class="ow">in</span> <span class="n">t</span><span class="o">.</span><span class="n">apply_transformation</span><span class="p">(</span>
                    <span class="n">structure</span><span class="p">,</span> <span class="n">return_ranked_list</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">nstructures_per_trans</span>
                <span class="p">):</span>
                    <span class="n">d</span><span class="p">[</span><span class="s2">&quot;transformation&quot;</span><span class="p">]</span> <span class="o">=</span> <span class="n">t</span>
                    <span class="n">structures</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">d</span><span class="p">)</span>
            <span class="k">else</span><span class="p">:</span>
                <span class="n">structures</span><span class="o">.</span><span class="n">append</span><span class="p">(</span>
                    <span class="p">{</span>
                        <span class="s2">&quot;transformation&quot;</span><span class="p">:</span> <span class="n">t</span><span class="p">,</span>
                        <span class="s2">&quot;structure&quot;</span><span class="p">:</span> <span class="n">t</span><span class="o">.</span><span class="n">apply_transformation</span><span class="p">(</span><span class="n">structure</span><span class="p">),</span>
                    <span class="p">}</span>
                <span class="p">)</span>
        <span class="k">return</span> <span class="n">structures</span></div>

    <span class="k">def</span> <span class="fm">__str__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="k">return</span> <span class="s2">&quot;Super Transformation : Transformations = &quot;</span> <span class="o">+</span> <span class="s2">&quot;</span><span class="si">{}</span><span class="s2">&quot;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span>
            <span class="s2">&quot; &quot;</span><span class="o">.</span><span class="n">join</span><span class="p">([</span><span class="nb">str</span><span class="p">(</span><span class="n">t</span><span class="p">)</span> <span class="k">for</span> <span class="n">t</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">_transformations</span><span class="p">])</span>
        <span class="p">)</span>

    <span class="k">def</span> <span class="fm">__repr__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="fm">__str__</span><span class="p">()</span>

    <span class="nd">@property</span>
    <span class="k">def</span> <span class="nf">inverse</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;Returns: None&quot;&quot;&quot;</span>
        <span class="k">return</span> <span class="kc">None</span>

    <span class="nd">@property</span>
    <span class="k">def</span> <span class="nf">is_one_to_many</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;Returns: True&quot;&quot;&quot;</span>
        <span class="k">return</span> <span class="kc">True</span></div>


<div class="viewcode-block" id="MultipleSubstitutionTransformation"><a class="viewcode-back" href="../../../pymatgen.transformations.advanced_transformations.html#pymatgen.transformations.advanced_transformations.MultipleSubstitutionTransformation">[docs]</a><span class="k">class</span> <span class="nc">MultipleSubstitutionTransformation</span><span class="p">:</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    Performs multiple substitutions on a structure. For example, can do a</span>
<span class="sd">    fractional replacement of Ge in LiGePS with a list of species, creating one</span>
<span class="sd">    structure for each substitution. Ordering is done using a dummy element so</span>
<span class="sd">    only one ordering must be done per substitution oxidation state. Charge</span>
<span class="sd">    balancing of the structure is optionally performed.</span>

<span class="sd">    .. note::</span>
<span class="sd">        There are no checks to make sure that removal fractions are possible</span>
<span class="sd">        and rounding may occur. Currently charge balancing only works for</span>
<span class="sd">        removal of species.</span>
<span class="sd">    &quot;&quot;&quot;</span>

    <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span>
        <span class="bp">self</span><span class="p">,</span>
        <span class="n">sp_to_replace</span><span class="p">,</span>
        <span class="n">r_fraction</span><span class="p">,</span>
        <span class="n">substitution_dict</span><span class="p">,</span>
        <span class="n">charge_balance_species</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
        <span class="n">order</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span>
    <span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Performs multiple fractional substitutions on a transmuter.</span>

<span class="sd">        Args:</span>
<span class="sd">            sp_to_replace: species to be replaced</span>
<span class="sd">            r_fraction: fraction of that specie to replace</span>
<span class="sd">            substitution_dict: dictionary of the format</span>
<span class="sd">                {2: [&quot;Mg&quot;, &quot;Ti&quot;, &quot;V&quot;, &quot;As&quot;, &quot;Cr&quot;, &quot;Ta&quot;, &quot;N&quot;, &quot;Nb&quot;],</span>
<span class="sd">                3: [&quot;Ru&quot;, &quot;Fe&quot;, &quot;Co&quot;, &quot;Ce&quot;, &quot;As&quot;, &quot;Cr&quot;, &quot;Ta&quot;, &quot;N&quot;, &quot;Nb&quot;],</span>
<span class="sd">                4: [&quot;Ru&quot;, &quot;V&quot;, &quot;Cr&quot;, &quot;Ta&quot;, &quot;N&quot;, &quot;Nb&quot;],</span>
<span class="sd">                5: [&quot;Ru&quot;, &quot;W&quot;, &quot;Mn&quot;]</span>
<span class="sd">                }</span>
<span class="sd">                The number is the charge used for each of the list of elements</span>
<span class="sd">                (an element can be present in multiple lists)</span>
<span class="sd">            charge_balance_species: If specified, will balance the charge on</span>
<span class="sd">                the structure using that specie.</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">sp_to_replace</span> <span class="o">=</span> <span class="n">sp_to_replace</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">r_fraction</span> <span class="o">=</span> <span class="n">r_fraction</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">substitution_dict</span> <span class="o">=</span> <span class="n">substitution_dict</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">charge_balance_species</span> <span class="o">=</span> <span class="n">charge_balance_species</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">order</span> <span class="o">=</span> <span class="n">order</span>

<div class="viewcode-block" id="MultipleSubstitutionTransformation.apply_transformation"><a class="viewcode-back" href="../../../pymatgen.transformations.advanced_transformations.html#pymatgen.transformations.advanced_transformations.MultipleSubstitutionTransformation.apply_transformation">[docs]</a>    <span class="k">def</span> <span class="nf">apply_transformation</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">structure</span><span class="p">,</span> <span class="n">return_ranked_list</span><span class="o">=</span><span class="kc">False</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Applies the transformation.</span>

<span class="sd">        Args:</span>
<span class="sd">            structure: Input Structure</span>
<span class="sd">            return_ranked_list: Number of structures to return.</span>

<span class="sd">        Returns:</span>
<span class="sd">            Structures with all substitutions applied.</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="k">if</span> <span class="ow">not</span> <span class="n">return_ranked_list</span><span class="p">:</span>
            <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span>
                <span class="s2">&quot;MultipleSubstitutionTransformation has no single&quot;</span>
                <span class="s2">&quot; best structure output. Must use&quot;</span>
                <span class="s2">&quot; return_ranked_list.&quot;</span>
            <span class="p">)</span>
        <span class="n">outputs</span> <span class="o">=</span> <span class="p">[]</span>
        <span class="k">for</span> <span class="n">charge</span><span class="p">,</span> <span class="n">el_list</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">substitution_dict</span><span class="o">.</span><span class="n">items</span><span class="p">():</span>
            <span class="n">mapping</span> <span class="o">=</span> <span class="p">{}</span>
            <span class="k">if</span> <span class="n">charge</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">:</span>
                <span class="n">sign</span> <span class="o">=</span> <span class="s2">&quot;+&quot;</span>
            <span class="k">else</span><span class="p">:</span>
                <span class="n">sign</span> <span class="o">=</span> <span class="s2">&quot;-&quot;</span>
            <span class="n">dummy_sp</span> <span class="o">=</span> <span class="s2">&quot;X</span><span class="si">{}{}</span><span class="s2">&quot;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">charge</span><span class="p">),</span> <span class="n">sign</span><span class="p">)</span>
            <span class="n">mapping</span><span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">sp_to_replace</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span>
                <span class="bp">self</span><span class="o">.</span><span class="n">sp_to_replace</span><span class="p">:</span> <span class="mi">1</span> <span class="o">-</span> <span class="bp">self</span><span class="o">.</span><span class="n">r_fraction</span><span class="p">,</span>
                <span class="n">dummy_sp</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">r_fraction</span><span class="p">,</span>
            <span class="p">}</span>
            <span class="n">trans</span> <span class="o">=</span> <span class="n">SubstitutionTransformation</span><span class="p">(</span><span class="n">mapping</span><span class="p">)</span>
            <span class="n">dummy_structure</span> <span class="o">=</span> <span class="n">trans</span><span class="o">.</span><span class="n">apply_transformation</span><span class="p">(</span><span class="n">structure</span><span class="p">)</span>
            <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">charge_balance_species</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
                <span class="n">cbt</span> <span class="o">=</span> <span class="n">ChargeBalanceTransformation</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">charge_balance_species</span><span class="p">)</span>
                <span class="n">dummy_structure</span> <span class="o">=</span> <span class="n">cbt</span><span class="o">.</span><span class="n">apply_transformation</span><span class="p">(</span><span class="n">dummy_structure</span><span class="p">)</span>
            <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">order</span><span class="p">:</span>
                <span class="n">trans</span> <span class="o">=</span> <span class="n">OrderDisorderedStructureTransformation</span><span class="p">()</span>
                <span class="n">dummy_structure</span> <span class="o">=</span> <span class="n">trans</span><span class="o">.</span><span class="n">apply_transformation</span><span class="p">(</span><span class="n">dummy_structure</span><span class="p">)</span>

            <span class="k">for</span> <span class="n">el</span> <span class="ow">in</span> <span class="n">el_list</span><span class="p">:</span>
                <span class="k">if</span> <span class="n">charge</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">:</span>
                    <span class="n">sign</span> <span class="o">=</span> <span class="s2">&quot;+&quot;</span>
                <span class="k">else</span><span class="p">:</span>
                    <span class="n">sign</span> <span class="o">=</span> <span class="s2">&quot;-&quot;</span>
                <span class="n">st</span> <span class="o">=</span> <span class="n">SubstitutionTransformation</span><span class="p">(</span>
                    <span class="p">{</span><span class="s2">&quot;X</span><span class="si">{}</span><span class="s2">+&quot;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">charge</span><span class="p">)):</span> <span class="s2">&quot;</span><span class="si">{}{}{}</span><span class="s2">&quot;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">el</span><span class="p">,</span> <span class="n">charge</span><span class="p">,</span> <span class="n">sign</span><span class="p">)}</span>
                <span class="p">)</span>
                <span class="n">new_structure</span> <span class="o">=</span> <span class="n">st</span><span class="o">.</span><span class="n">apply_transformation</span><span class="p">(</span><span class="n">dummy_structure</span><span class="p">)</span>
                <span class="n">outputs</span><span class="o">.</span><span class="n">append</span><span class="p">({</span><span class="s2">&quot;structure&quot;</span><span class="p">:</span> <span class="n">new_structure</span><span class="p">})</span>
        <span class="k">return</span> <span class="n">outputs</span></div>

    <span class="k">def</span> <span class="fm">__str__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="k">return</span> <span class="s2">&quot;Multiple Substitution Transformation : Substitution on &quot;</span> <span class="o">+</span> <span class="s2">&quot;</span><span class="si">{}</span><span class="s2">&quot;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">sp_to_replace</span>
        <span class="p">)</span>

    <span class="k">def</span> <span class="fm">__repr__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="fm">__str__</span><span class="p">()</span>

    <span class="nd">@property</span>
    <span class="k">def</span> <span class="nf">inverse</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;Returns: None&quot;&quot;&quot;</span>
        <span class="k">return</span> <span class="kc">None</span>

    <span class="nd">@property</span>
    <span class="k">def</span> <span class="nf">is_one_to_many</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;Returns: True&quot;&quot;&quot;</span>
        <span class="k">return</span> <span class="kc">True</span></div>


<div class="viewcode-block" id="EnumerateStructureTransformation"><a class="viewcode-back" href="../../../pymatgen.transformations.advanced_transformations.html#pymatgen.transformations.advanced_transformations.EnumerateStructureTransformation">[docs]</a><span class="k">class</span> <span class="nc">EnumerateStructureTransformation</span><span class="p">(</span><span class="n">AbstractTransformation</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    Order a disordered structure using enumlib. For complete orderings, this</span>
<span class="sd">    generally produces fewer structures that the OrderDisorderedStructure</span>
<span class="sd">    transformation, and at a much faster speed.</span>
<span class="sd">    &quot;&quot;&quot;</span>

    <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span>
        <span class="bp">self</span><span class="p">,</span>
        <span class="n">min_cell_size</span><span class="o">=</span><span class="mi">1</span><span class="p">,</span>
        <span class="n">max_cell_size</span><span class="o">=</span><span class="mi">1</span><span class="p">,</span>
        <span class="n">symm_prec</span><span class="o">=</span><span class="mf">0.1</span><span class="p">,</span>
        <span class="n">refine_structure</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span>
        <span class="n">enum_precision_parameter</span><span class="o">=</span><span class="mf">0.001</span><span class="p">,</span>
        <span class="n">check_ordered_symmetry</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span>
        <span class="n">max_disordered_sites</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
        <span class="n">sort_criteria</span><span class="o">=</span><span class="s2">&quot;ewald&quot;</span><span class="p">,</span>
        <span class="n">timeout</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
    <span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Args:</span>
<span class="sd">            min_cell_size:</span>
<span class="sd">                The minimum cell size wanted. Must be an int. Defaults to 1.</span>
<span class="sd">            max_cell_size:</span>
<span class="sd">                The maximum cell size wanted. Must be an int. Defaults to 1.</span>
<span class="sd">            symm_prec:</span>
<span class="sd">                Tolerance to use for symmetry.</span>
<span class="sd">            refine_structure:</span>
<span class="sd">                This parameter has the same meaning as in enumlib_caller.</span>
<span class="sd">                If you are starting from a structure that has been relaxed via</span>
<span class="sd">                some electronic structure code, it is usually much better to</span>
<span class="sd">                start with symmetry determination and then obtain a refined</span>
<span class="sd">                structure. The refined structure have cell parameters and</span>
<span class="sd">                atomic positions shifted to the expected symmetry positions,</span>
<span class="sd">                which makes it much less sensitive precision issues in enumlib.</span>
<span class="sd">                If you are already starting from an experimental cif, refinment</span>
<span class="sd">                should have already been done and it is not necessary. Defaults</span>
<span class="sd">                to False.</span>
<span class="sd">            enum_precision_parameter (float): Finite precision parameter for</span>
<span class="sd">                enumlib. Default of 0.001 is usually ok, but you might need to</span>
<span class="sd">                tweak it for certain cells.</span>
<span class="sd">            check_ordered_symmetry (bool): Whether to check the symmetry of</span>
<span class="sd">                the ordered sites. If the symmetry of the ordered sites is</span>
<span class="sd">                lower, the lowest symmetry ordered sites is included in the</span>
<span class="sd">                enumeration. This is important if the ordered sites break</span>
<span class="sd">                symmetry in a way that is important getting possible</span>
<span class="sd">                structures. But sometimes including ordered sites</span>
<span class="sd">                slows down enumeration to the point that it cannot be</span>
<span class="sd">                completed. Switch to False in those cases. Defaults to True.</span>
<span class="sd">            max_disordered_sites (int):</span>
<span class="sd">                An alternate parameter to max_cell size. Will sequentially try</span>
<span class="sd">                larger and larger cell sizes until (i) getting a result or (ii)</span>
<span class="sd">                the number of disordered sites in the cell exceeds</span>
<span class="sd">                max_disordered_sites. Must set max_cell_size to None when using</span>
<span class="sd">                this parameter.</span>
<span class="sd">            sort_criteria (str): Sort by Ewald energy (&quot;ewald&quot;, must have oxidation</span>
<span class="sd">                states and slow) or by number of sites (&quot;nsites&quot;, much faster).</span>
<span class="sd">            timeout (float): timeout in minutes to pass to EnumlibAdaptor</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">symm_prec</span> <span class="o">=</span> <span class="n">symm_prec</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">min_cell_size</span> <span class="o">=</span> <span class="n">min_cell_size</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">max_cell_size</span> <span class="o">=</span> <span class="n">max_cell_size</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">refine_structure</span> <span class="o">=</span> <span class="n">refine_structure</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">enum_precision_parameter</span> <span class="o">=</span> <span class="n">enum_precision_parameter</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">check_ordered_symmetry</span> <span class="o">=</span> <span class="n">check_ordered_symmetry</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">max_disordered_sites</span> <span class="o">=</span> <span class="n">max_disordered_sites</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">sort_criteria</span> <span class="o">=</span> <span class="n">sort_criteria</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">timeout</span> <span class="o">=</span> <span class="n">timeout</span>

        <span class="k">if</span> <span class="n">max_cell_size</span> <span class="ow">and</span> <span class="n">max_disordered_sites</span><span class="p">:</span>
            <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span>
                <span class="s2">&quot;Cannot set both max_cell_size and &quot;</span> <span class="s2">&quot;max_disordered_sites!&quot;</span>
            <span class="p">)</span>

<div class="viewcode-block" id="EnumerateStructureTransformation.apply_transformation"><a class="viewcode-back" href="../../../pymatgen.transformations.advanced_transformations.html#pymatgen.transformations.advanced_transformations.EnumerateStructureTransformation.apply_transformation">[docs]</a>    <span class="k">def</span> <span class="nf">apply_transformation</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">structure</span><span class="p">,</span> <span class="n">return_ranked_list</span><span class="o">=</span><span class="kc">False</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Returns either a single ordered structure or a sequence of all ordered</span>
<span class="sd">        structures.</span>

<span class="sd">        Args:</span>
<span class="sd">            structure: Structure to order.</span>
<span class="sd">            return_ranked_list (bool): Whether or not multiple structures are</span>
<span class="sd">                returned. If return_ranked_list is a number, that number of</span>
<span class="sd">                structures is returned.</span>

<span class="sd">        Returns:</span>
<span class="sd">            Depending on returned_ranked list, either a transformed structure</span>
<span class="sd">            or a list of dictionaries, where each dictionary is of the form</span>
<span class="sd">            {&quot;structure&quot; = .... , &quot;other_arguments&quot;}</span>

<span class="sd">            The list of ordered structures is ranked by ewald energy / atom, if</span>
<span class="sd">            the input structure is an oxidation state decorated structure.</span>
<span class="sd">            Otherwise, it is ranked by number of sites, with smallest number of</span>
<span class="sd">            sites first.</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="k">try</span><span class="p">:</span>
            <span class="n">num_to_return</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">return_ranked_list</span><span class="p">)</span>
        <span class="k">except</span> <span class="ne">ValueError</span><span class="p">:</span>
            <span class="n">num_to_return</span> <span class="o">=</span> <span class="mi">1</span>

        <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">refine_structure</span><span class="p">:</span>
            <span class="n">finder</span> <span class="o">=</span> <span class="n">SpacegroupAnalyzer</span><span class="p">(</span><span class="n">structure</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">symm_prec</span><span class="p">)</span>
            <span class="n">structure</span> <span class="o">=</span> <span class="n">finder</span><span class="o">.</span><span class="n">get_refined_structure</span><span class="p">()</span>

        <span class="n">contains_oxidation_state</span> <span class="o">=</span> <span class="nb">all</span><span class="p">(</span>
            <span class="p">[</span>
                <span class="nb">hasattr</span><span class="p">(</span><span class="n">sp</span><span class="p">,</span> <span class="s2">&quot;oxi_state&quot;</span><span class="p">)</span> <span class="ow">and</span> <span class="n">sp</span><span class="o">.</span><span class="n">oxi_state</span> <span class="o">!=</span> <span class="mi">0</span>
                <span class="k">for</span> <span class="n">sp</span> <span class="ow">in</span> <span class="n">structure</span><span class="o">.</span><span class="n">composition</span><span class="o">.</span><span class="n">elements</span>
            <span class="p">]</span>
        <span class="p">)</span>

        <span class="n">structures</span> <span class="o">=</span> <span class="kc">None</span>

        <span class="k">if</span> <span class="n">structure</span><span class="o">.</span><span class="n">is_ordered</span><span class="p">:</span>
            <span class="n">warn</span><span class="p">(</span>
                <span class="s2">&quot;Enumeration skipped for structure with composition </span><span class="si">{}</span><span class="s2"> &quot;</span>
                <span class="s2">&quot;because it is ordered&quot;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">structure</span><span class="o">.</span><span class="n">composition</span><span class="p">)</span>
            <span class="p">)</span>
            <span class="n">structures</span> <span class="o">=</span> <span class="p">[</span><span class="n">structure</span><span class="o">.</span><span class="n">copy</span><span class="p">()]</span>

        <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">max_disordered_sites</span><span class="p">:</span>
            <span class="n">ndisordered</span> <span class="o">=</span> <span class="nb">sum</span><span class="p">([</span><span class="mi">1</span> <span class="k">for</span> <span class="n">site</span> <span class="ow">in</span> <span class="n">structure</span> <span class="k">if</span> <span class="ow">not</span> <span class="n">site</span><span class="o">.</span><span class="n">is_ordered</span><span class="p">])</span>
            <span class="k">if</span> <span class="n">ndisordered</span> <span class="o">&gt;</span> <span class="bp">self</span><span class="o">.</span><span class="n">max_disordered_sites</span><span class="p">:</span>
                <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span>
                    <span class="s2">&quot;Too many disordered sites! (</span><span class="si">{}</span><span class="s2"> &gt; </span><span class="si">{}</span><span class="s2">)&quot;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span>
                        <span class="n">ndisordered</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">max_disordered_sites</span>
                    <span class="p">)</span>
                <span class="p">)</span>
            <span class="n">max_cell_sizes</span> <span class="o">=</span> <span class="nb">range</span><span class="p">(</span>
                <span class="bp">self</span><span class="o">.</span><span class="n">min_cell_size</span><span class="p">,</span>
                <span class="nb">int</span><span class="p">(</span><span class="n">math</span><span class="o">.</span><span class="n">floor</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">max_disordered_sites</span> <span class="o">/</span> <span class="n">ndisordered</span><span class="p">))</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span>
            <span class="p">)</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="n">max_cell_sizes</span> <span class="o">=</span> <span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">max_cell_size</span><span class="p">]</span>

        <span class="k">for</span> <span class="n">max_cell_size</span> <span class="ow">in</span> <span class="n">max_cell_sizes</span><span class="p">:</span>
            <span class="n">adaptor</span> <span class="o">=</span> <span class="n">EnumlibAdaptor</span><span class="p">(</span>
                <span class="n">structure</span><span class="p">,</span>
                <span class="n">min_cell_size</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">min_cell_size</span><span class="p">,</span>
                <span class="n">max_cell_size</span><span class="o">=</span><span class="n">max_cell_size</span><span class="p">,</span>
                <span class="n">symm_prec</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">symm_prec</span><span class="p">,</span>
                <span class="n">refine_structure</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span>
                <span class="n">enum_precision_parameter</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">enum_precision_parameter</span><span class="p">,</span>
                <span class="n">check_ordered_symmetry</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">check_ordered_symmetry</span><span class="p">,</span>
                <span class="n">timeout</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">timeout</span><span class="p">,</span>
            <span class="p">)</span>
            <span class="k">try</span><span class="p">:</span>
                <span class="n">adaptor</span><span class="o">.</span><span class="n">run</span><span class="p">()</span>
            <span class="k">except</span> <span class="n">EnumError</span><span class="p">:</span>
                <span class="n">warn</span><span class="p">(</span><span class="s2">&quot;Unable to enumerate for max_cell_size = </span><span class="si">{}</span><span class="s2">&quot;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">max_cell_size</span><span class="p">))</span>
            <span class="n">structures</span> <span class="o">=</span> <span class="n">adaptor</span><span class="o">.</span><span class="n">structures</span>
            <span class="k">if</span> <span class="n">structures</span><span class="p">:</span>
                <span class="k">break</span>

        <span class="k">if</span> <span class="n">structures</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
            <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s2">&quot;Unable to enumerate&quot;</span><span class="p">)</span>

        <span class="n">original_latt</span> <span class="o">=</span> <span class="n">structure</span><span class="o">.</span><span class="n">lattice</span>
        <span class="n">inv_latt</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">linalg</span><span class="o">.</span><span class="n">inv</span><span class="p">(</span><span class="n">original_latt</span><span class="o">.</span><span class="n">matrix</span><span class="p">)</span>
        <span class="n">ewald_matrices</span> <span class="o">=</span> <span class="p">{}</span>
        <span class="n">all_structures</span> <span class="o">=</span> <span class="p">[]</span>
        <span class="k">for</span> <span class="n">s</span> <span class="ow">in</span> <span class="n">structures</span><span class="p">:</span>
            <span class="n">new_latt</span> <span class="o">=</span> <span class="n">s</span><span class="o">.</span><span class="n">lattice</span>
            <span class="n">transformation</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">dot</span><span class="p">(</span><span class="n">new_latt</span><span class="o">.</span><span class="n">matrix</span><span class="p">,</span> <span class="n">inv_latt</span><span class="p">)</span>
            <span class="n">transformation</span> <span class="o">=</span> <span class="nb">tuple</span><span class="p">(</span>
                <span class="p">[</span><span class="nb">tuple</span><span class="p">([</span><span class="nb">int</span><span class="p">(</span><span class="nb">round</span><span class="p">(</span><span class="n">cell</span><span class="p">))</span> <span class="k">for</span> <span class="n">cell</span> <span class="ow">in</span> <span class="n">row</span><span class="p">])</span> <span class="k">for</span> <span class="n">row</span> <span class="ow">in</span> <span class="n">transformation</span><span class="p">]</span>
            <span class="p">)</span>
            <span class="k">if</span> <span class="n">contains_oxidation_state</span> <span class="ow">and</span> <span class="bp">self</span><span class="o">.</span><span class="n">sort_criteria</span> <span class="o">==</span> <span class="s2">&quot;ewald&quot;</span><span class="p">:</span>
                <span class="k">if</span> <span class="n">transformation</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">ewald_matrices</span><span class="p">:</span>
                    <span class="n">s_supercell</span> <span class="o">=</span> <span class="n">structure</span> <span class="o">*</span> <span class="n">transformation</span>
                    <span class="n">ewald</span> <span class="o">=</span> <span class="n">EwaldSummation</span><span class="p">(</span><span class="n">s_supercell</span><span class="p">)</span>
                    <span class="n">ewald_matrices</span><span class="p">[</span><span class="n">transformation</span><span class="p">]</span> <span class="o">=</span> <span class="n">ewald</span>
                <span class="k">else</span><span class="p">:</span>
                    <span class="n">ewald</span> <span class="o">=</span> <span class="n">ewald_matrices</span><span class="p">[</span><span class="n">transformation</span><span class="p">]</span>
                <span class="n">energy</span> <span class="o">=</span> <span class="n">ewald</span><span class="o">.</span><span class="n">compute_sub_structure</span><span class="p">(</span><span class="n">s</span><span class="p">)</span>
                <span class="n">all_structures</span><span class="o">.</span><span class="n">append</span><span class="p">(</span>
                    <span class="p">{</span><span class="s2">&quot;num_sites&quot;</span><span class="p">:</span> <span class="nb">len</span><span class="p">(</span><span class="n">s</span><span class="p">),</span> <span class="s2">&quot;energy&quot;</span><span class="p">:</span> <span class="n">energy</span><span class="p">,</span> <span class="s2">&quot;structure&quot;</span><span class="p">:</span> <span class="n">s</span><span class="p">}</span>
                <span class="p">)</span>
            <span class="k">else</span><span class="p">:</span>
                <span class="n">all_structures</span><span class="o">.</span><span class="n">append</span><span class="p">({</span><span class="s2">&quot;num_sites&quot;</span><span class="p">:</span> <span class="nb">len</span><span class="p">(</span><span class="n">s</span><span class="p">),</span> <span class="s2">&quot;structure&quot;</span><span class="p">:</span> <span class="n">s</span><span class="p">})</span>

        <span class="k">def</span> <span class="nf">sort_func</span><span class="p">(</span><span class="n">s</span><span class="p">):</span>
            <span class="k">return</span> <span class="p">(</span>
                <span class="n">s</span><span class="p">[</span><span class="s2">&quot;energy&quot;</span><span class="p">]</span> <span class="o">/</span> <span class="n">s</span><span class="p">[</span><span class="s2">&quot;num_sites&quot;</span><span class="p">]</span>
                <span class="k">if</span> <span class="n">contains_oxidation_state</span> <span class="ow">and</span> <span class="bp">self</span><span class="o">.</span><span class="n">sort_criteria</span> <span class="o">==</span> <span class="s2">&quot;ewald&quot;</span>
                <span class="k">else</span> <span class="n">s</span><span class="p">[</span><span class="s2">&quot;num_sites&quot;</span><span class="p">]</span>
            <span class="p">)</span>

        <span class="bp">self</span><span class="o">.</span><span class="n">_all_structures</span> <span class="o">=</span> <span class="nb">sorted</span><span class="p">(</span><span class="n">all_structures</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="n">sort_func</span><span class="p">)</span>

        <span class="k">if</span> <span class="n">return_ranked_list</span><span class="p">:</span>
            <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_all_structures</span><span class="p">[</span><span class="mi">0</span><span class="p">:</span><span class="n">num_to_return</span><span class="p">]</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_all_structures</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="s2">&quot;structure&quot;</span><span class="p">]</span></div>

    <span class="k">def</span> <span class="fm">__str__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="k">return</span> <span class="s2">&quot;EnumerateStructureTransformation&quot;</span>

    <span class="k">def</span> <span class="fm">__repr__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="fm">__str__</span><span class="p">()</span>

    <span class="nd">@property</span>
    <span class="k">def</span> <span class="nf">inverse</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;Returns: None&quot;&quot;&quot;</span>
        <span class="k">return</span> <span class="kc">None</span>

    <span class="nd">@property</span>
    <span class="k">def</span> <span class="nf">is_one_to_many</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;Returns: True&quot;&quot;&quot;</span>
        <span class="k">return</span> <span class="kc">True</span></div>


<div class="viewcode-block" id="SubstitutionPredictorTransformation"><a class="viewcode-back" href="../../../pymatgen.transformations.advanced_transformations.html#pymatgen.transformations.advanced_transformations.SubstitutionPredictorTransformation">[docs]</a><span class="k">class</span> <span class="nc">SubstitutionPredictorTransformation</span><span class="p">(</span><span class="n">AbstractTransformation</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    This transformation takes a structure and uses the structure</span>
<span class="sd">    prediction module to find likely site substitutions.</span>
<span class="sd">    &quot;&quot;&quot;</span>

    <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">threshold</span><span class="o">=</span><span class="mf">1e-2</span><span class="p">,</span> <span class="n">scale_volumes</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
        <span class="sa">r</span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Args:</span>
<span class="sd">            threshold: Threshold for substitution.</span>
<span class="sd">            scale_volumes: Whether to scale volumes after substitution.</span>
<span class="sd">            **kwargs: Args for SubstitutionProbability class lambda_table, alpha</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">kwargs</span> <span class="o">=</span> <span class="n">kwargs</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">threshold</span> <span class="o">=</span> <span class="n">threshold</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">scale_volumes</span> <span class="o">=</span> <span class="n">scale_volumes</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">_substitutor</span> <span class="o">=</span> <span class="n">SubstitutionPredictor</span><span class="p">(</span><span class="n">threshold</span><span class="o">=</span><span class="n">threshold</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">)</span>

<div class="viewcode-block" id="SubstitutionPredictorTransformation.apply_transformation"><a class="viewcode-back" href="../../../pymatgen.transformations.advanced_transformations.html#pymatgen.transformations.advanced_transformations.SubstitutionPredictorTransformation.apply_transformation">[docs]</a>    <span class="k">def</span> <span class="nf">apply_transformation</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">structure</span><span class="p">,</span> <span class="n">return_ranked_list</span><span class="o">=</span><span class="kc">False</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Applies the transformation.</span>

<span class="sd">        Args:</span>
<span class="sd">            structure: Input Structure</span>
<span class="sd">            return_ranked_list: Number of structures to return.</span>

<span class="sd">        Returns:</span>
<span class="sd">            Predicted Structures.</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="k">if</span> <span class="ow">not</span> <span class="n">return_ranked_list</span><span class="p">:</span>
            <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span>
                <span class="s2">&quot;SubstitutionPredictorTransformation doesn&#39;t&quot;</span>
                <span class="s2">&quot; support returning 1 structure&quot;</span>
            <span class="p">)</span>

        <span class="n">preds</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_substitutor</span><span class="o">.</span><span class="n">composition_prediction</span><span class="p">(</span>
            <span class="n">structure</span><span class="o">.</span><span class="n">composition</span><span class="p">,</span> <span class="n">to_this_composition</span><span class="o">=</span><span class="kc">False</span>
        <span class="p">)</span>
        <span class="n">preds</span><span class="o">.</span><span class="n">sort</span><span class="p">(</span><span class="n">key</span><span class="o">=</span><span class="k">lambda</span> <span class="n">x</span><span class="p">:</span> <span class="n">x</span><span class="p">[</span><span class="s2">&quot;probability&quot;</span><span class="p">],</span> <span class="n">reverse</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>

        <span class="n">outputs</span> <span class="o">=</span> <span class="p">[]</span>
        <span class="k">for</span> <span class="n">pred</span> <span class="ow">in</span> <span class="n">preds</span><span class="p">:</span>
            <span class="n">st</span> <span class="o">=</span> <span class="n">SubstitutionTransformation</span><span class="p">(</span><span class="n">pred</span><span class="p">[</span><span class="s2">&quot;substitutions&quot;</span><span class="p">])</span>
            <span class="n">output</span> <span class="o">=</span> <span class="p">{</span>
                <span class="s2">&quot;structure&quot;</span><span class="p">:</span> <span class="n">st</span><span class="o">.</span><span class="n">apply_transformation</span><span class="p">(</span><span class="n">structure</span><span class="p">),</span>
                <span class="s2">&quot;probability&quot;</span><span class="p">:</span> <span class="n">pred</span><span class="p">[</span><span class="s2">&quot;probability&quot;</span><span class="p">],</span>
                <span class="s2">&quot;threshold&quot;</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">threshold</span><span class="p">,</span>
                <span class="s2">&quot;substitutions&quot;</span><span class="p">:</span> <span class="p">{},</span>
            <span class="p">}</span>

            <span class="c1"># dictionary keys have to be converted to strings for JSON</span>
            <span class="k">for</span> <span class="n">key</span><span class="p">,</span> <span class="n">value</span> <span class="ow">in</span> <span class="n">pred</span><span class="p">[</span><span class="s2">&quot;substitutions&quot;</span><span class="p">]</span><span class="o">.</span><span class="n">items</span><span class="p">():</span>
                <span class="n">output</span><span class="p">[</span><span class="s2">&quot;substitutions&quot;</span><span class="p">][</span><span class="nb">str</span><span class="p">(</span><span class="n">key</span><span class="p">)]</span> <span class="o">=</span> <span class="nb">str</span><span class="p">(</span><span class="n">value</span><span class="p">)</span>
            <span class="n">outputs</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">output</span><span class="p">)</span>
        <span class="k">return</span> <span class="n">outputs</span></div>

    <span class="k">def</span> <span class="fm">__str__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="k">return</span> <span class="s2">&quot;SubstitutionPredictorTransformation&quot;</span>

    <span class="k">def</span> <span class="fm">__repr__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="fm">__str__</span><span class="p">()</span>

    <span class="nd">@property</span>
    <span class="k">def</span> <span class="nf">inverse</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;Returns: None&quot;&quot;&quot;</span>
        <span class="k">return</span> <span class="kc">None</span>

    <span class="nd">@property</span>
    <span class="k">def</span> <span class="nf">is_one_to_many</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;Returns: True&quot;&quot;&quot;</span>
        <span class="k">return</span> <span class="kc">True</span></div>


<div class="viewcode-block" id="MagOrderParameterConstraint"><a class="viewcode-back" href="../../../pymatgen.transformations.advanced_transformations.html#pymatgen.transformations.advanced_transformations.MagOrderParameterConstraint">[docs]</a><span class="k">class</span> <span class="nc">MagOrderParameterConstraint</span><span class="p">(</span><span class="n">MSONable</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    This class can be used to supply MagOrderingTransformation</span>
<span class="sd">    to just a specific subset of species or sites that satisfy the</span>
<span class="sd">    provided constraints. This can be useful for setting an order</span>
<span class="sd">    parameters for, for example, ferrimagnetic structures which</span>
<span class="sd">    might order on certain motifs, with the global order parameter</span>
<span class="sd">    dependent on how many sites satisfy that motif.</span>
<span class="sd">    &quot;&quot;&quot;</span>

    <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span>
        <span class="bp">self</span><span class="p">,</span>
        <span class="n">order_parameter</span><span class="p">,</span>
        <span class="n">species_constraints</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
        <span class="n">site_constraint_name</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
        <span class="n">site_constraints</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
    <span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        :param order_parameter (float): any number from 0.0 to 1.0,</span>
<span class="sd">            typically 0.5 (antiferromagnetic) or 1.0 (ferromagnetic)</span>
<span class="sd">        :param species_constraint (list): str or list of strings</span>
<span class="sd">            of Specie symbols that the constraint should apply to</span>
<span class="sd">        :param site_constraint_name (str): name of the site property</span>
<span class="sd">            that the constraint should apply to, e.g. &quot;coordination_no&quot;</span>
<span class="sd">        :param site_constraints (list): list of values of the site</span>
<span class="sd">            property that the constraints should apply to</span>
<span class="sd">        &quot;&quot;&quot;</span>

        <span class="c1"># validation</span>
        <span class="k">if</span> <span class="n">site_constraints</span> <span class="ow">and</span> <span class="n">site_constraints</span> <span class="o">!=</span> <span class="p">[</span><span class="kc">None</span><span class="p">]</span> <span class="ow">and</span> <span class="ow">not</span> <span class="n">site_constraint_name</span><span class="p">:</span>
            <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s2">&quot;Specify the name of the site constraint.&quot;</span><span class="p">)</span>
        <span class="k">elif</span> <span class="ow">not</span> <span class="n">site_constraints</span> <span class="ow">and</span> <span class="n">site_constraint_name</span><span class="p">:</span>
            <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s2">&quot;Please specify some site constraints.&quot;</span><span class="p">)</span>
        <span class="k">if</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">species_constraints</span><span class="p">,</span> <span class="nb">list</span><span class="p">):</span>
            <span class="n">species_constraints</span> <span class="o">=</span> <span class="p">[</span><span class="n">species_constraints</span><span class="p">]</span>
        <span class="k">if</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">site_constraints</span><span class="p">,</span> <span class="nb">list</span><span class="p">):</span>
            <span class="n">site_constraints</span> <span class="o">=</span> <span class="p">[</span><span class="n">site_constraints</span><span class="p">]</span>

        <span class="k">if</span> <span class="n">order_parameter</span> <span class="o">&gt;</span> <span class="mi">1</span> <span class="ow">or</span> <span class="n">order_parameter</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">:</span>
            <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s2">&quot;Order parameter must lie between 0 and 1&quot;</span><span class="p">)</span>
        <span class="k">elif</span> <span class="n">order_parameter</span> <span class="o">!=</span> <span class="mf">0.5</span><span class="p">:</span>
            <span class="n">warnings</span><span class="o">.</span><span class="n">warn</span><span class="p">(</span>
                <span class="s2">&quot;Use care when using a non-standard order parameter, &quot;</span>
                <span class="s2">&quot;though it can be useful in some cases it can also &quot;</span>
                <span class="s2">&quot;lead to unintended behavior. Consult documentation.&quot;</span>
            <span class="p">)</span>

        <span class="bp">self</span><span class="o">.</span><span class="n">order_parameter</span> <span class="o">=</span> <span class="n">order_parameter</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">species_constraints</span> <span class="o">=</span> <span class="n">species_constraints</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">site_constraint_name</span> <span class="o">=</span> <span class="n">site_constraint_name</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">site_constraints</span> <span class="o">=</span> <span class="n">site_constraints</span>

<div class="viewcode-block" id="MagOrderParameterConstraint.satisfies_constraint"><a class="viewcode-back" href="../../../pymatgen.transformations.advanced_transformations.html#pymatgen.transformations.advanced_transformations.MagOrderParameterConstraint.satisfies_constraint">[docs]</a>    <span class="k">def</span> <span class="nf">satisfies_constraint</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">site</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Checks if a periodic site satisfies the constraint.</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="k">if</span> <span class="ow">not</span> <span class="n">site</span><span class="o">.</span><span class="n">is_ordered</span><span class="p">:</span>
            <span class="k">return</span> <span class="kc">False</span>

        <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">species_constraints</span> <span class="ow">and</span> <span class="nb">str</span><span class="p">(</span><span class="n">site</span><span class="o">.</span><span class="n">specie</span><span class="p">)</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">species_constraints</span><span class="p">:</span>
            <span class="n">satisfies_constraints</span> <span class="o">=</span> <span class="kc">True</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="n">satisfies_constraints</span> <span class="o">=</span> <span class="kc">False</span>

        <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">site_constraint_name</span> <span class="ow">and</span> <span class="bp">self</span><span class="o">.</span><span class="n">site_constraint_name</span> <span class="ow">in</span> <span class="n">site</span><span class="o">.</span><span class="n">properties</span><span class="p">:</span>
            <span class="n">prop</span> <span class="o">=</span> <span class="n">site</span><span class="o">.</span><span class="n">properties</span><span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">site_constraint_name</span><span class="p">]</span>
            <span class="k">if</span> <span class="n">prop</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">site_constraints</span><span class="p">:</span>
                <span class="n">satisfies_constraints</span> <span class="o">=</span> <span class="kc">True</span>
            <span class="k">else</span><span class="p">:</span>
                <span class="n">satisfies_constraints</span> <span class="o">=</span> <span class="kc">False</span>

        <span class="k">return</span> <span class="n">satisfies_constraints</span></div></div>


<div class="viewcode-block" id="MagOrderingTransformation"><a class="viewcode-back" href="../../../pymatgen.transformations.advanced_transformations.html#pymatgen.transformations.advanced_transformations.MagOrderingTransformation">[docs]</a><span class="k">class</span> <span class="nc">MagOrderingTransformation</span><span class="p">(</span><span class="n">AbstractTransformation</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    This transformation takes a structure and returns a list of collinear</span>
<span class="sd">    magnetic orderings. For disordered structures, make an ordered</span>
<span class="sd">    approximation first.</span>
<span class="sd">    &quot;&quot;&quot;</span>

    <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span>
        <span class="bp">self</span><span class="p">,</span>
        <span class="n">mag_species_spin</span><span class="p">,</span>
        <span class="n">order_parameter</span><span class="o">=</span><span class="mf">0.5</span><span class="p">,</span>
        <span class="n">energy_model</span><span class="o">=</span><span class="n">SymmetryModel</span><span class="p">(),</span>
        <span class="o">**</span><span class="n">kwargs</span>
    <span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        :param mag_species_spin: A mapping of elements/species to their</span>
<span class="sd">            spin magnitudes, e.g. {&quot;Fe3+&quot;: 5, &quot;Mn3+&quot;: 4}</span>
<span class="sd">        :param order_parameter (float or list): if float, a specifies a</span>
<span class="sd">            global order parameter and can take values from 0.0 to 1.0</span>
<span class="sd">            (e.g. 0.5 for antiferromagnetic or 1.0 for ferromagnetic), if</span>
<span class="sd">            list has to be a list of</span>
<span class="sd">            :class: `pymatgen.transformations.advanced_transformations.MagOrderParameterConstraint`</span>
<span class="sd">            to specify more complicated orderings, see documentation for</span>
<span class="sd">            MagOrderParameterConstraint more details on usage</span>
<span class="sd">        :param energy_model: Energy model to rank the returned structures,</span>
<span class="sd">            see :mod: `pymatgen.analysis.energy_models` for more information (note</span>
<span class="sd">            that this is not necessarily a physical energy). By default, returned</span>
<span class="sd">            structures use SymmetryModel() which ranks structures from most</span>
<span class="sd">            symmetric to least.</span>
<span class="sd">        :param kwargs: Additional kwargs that are passed to</span>
<span class="sd">        :class:`EnumerateStructureTransformation` such as min_cell_size etc.</span>
<span class="sd">        &quot;&quot;&quot;</span>

        <span class="c1"># checking for sensible order_parameter values</span>
        <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">order_parameter</span><span class="p">,</span> <span class="nb">float</span><span class="p">):</span>
            <span class="c1"># convert to constraint format</span>
            <span class="n">order_parameter</span> <span class="o">=</span> <span class="p">[</span>
                <span class="n">MagOrderParameterConstraint</span><span class="p">(</span>
                    <span class="n">order_parameter</span><span class="o">=</span><span class="n">order_parameter</span><span class="p">,</span>
                    <span class="n">species_constraints</span><span class="o">=</span><span class="nb">list</span><span class="p">(</span><span class="n">mag_species_spin</span><span class="o">.</span><span class="n">keys</span><span class="p">()),</span>
                <span class="p">)</span>
            <span class="p">]</span>
        <span class="k">elif</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">order_parameter</span><span class="p">,</span> <span class="nb">list</span><span class="p">):</span>
            <span class="n">ops</span> <span class="o">=</span> <span class="p">[</span>
                <span class="nb">isinstance</span><span class="p">(</span><span class="n">item</span><span class="p">,</span> <span class="n">MagOrderParameterConstraint</span><span class="p">)</span>
                <span class="k">for</span> <span class="n">item</span> <span class="ow">in</span> <span class="n">order_parameter</span>
            <span class="p">]</span>
            <span class="k">if</span> <span class="ow">not</span> <span class="nb">any</span><span class="p">(</span><span class="n">ops</span><span class="p">):</span>
                <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s2">&quot;Order parameter not correctly defined.&quot;</span><span class="p">)</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s2">&quot;Order parameter not correctly defined.&quot;</span><span class="p">)</span>

        <span class="bp">self</span><span class="o">.</span><span class="n">mag_species_spin</span> <span class="o">=</span> <span class="n">mag_species_spin</span>
        <span class="c1"># store order parameter constraints as dicts to save implementing</span>
        <span class="c1"># to/from dict methods for MSONable compatibility</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">order_parameter</span> <span class="o">=</span> <span class="p">[</span><span class="n">op</span><span class="o">.</span><span class="n">as_dict</span><span class="p">()</span> <span class="k">for</span> <span class="n">op</span> <span class="ow">in</span> <span class="n">order_parameter</span><span class="p">]</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">energy_model</span> <span class="o">=</span> <span class="n">energy_model</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">enum_kwargs</span> <span class="o">=</span> <span class="n">kwargs</span>

<div class="viewcode-block" id="MagOrderingTransformation.determine_min_cell"><a class="viewcode-back" href="../../../pymatgen.transformations.advanced_transformations.html#pymatgen.transformations.advanced_transformations.MagOrderingTransformation.determine_min_cell">[docs]</a>    <span class="nd">@staticmethod</span>
    <span class="k">def</span> <span class="nf">determine_min_cell</span><span class="p">(</span><span class="n">disordered_structure</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Determine the smallest supercell that is able to enumerate</span>
<span class="sd">        the provided structure with the given order parameter</span>
<span class="sd">        &quot;&quot;&quot;</span>

        <span class="k">def</span> <span class="nf">lcm</span><span class="p">(</span><span class="n">n1</span><span class="p">,</span> <span class="n">n2</span><span class="p">):</span>
            <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">            Find least common multiple of two numbers</span>
<span class="sd">            &quot;&quot;&quot;</span>
            <span class="k">return</span> <span class="n">n1</span> <span class="o">*</span> <span class="n">n2</span> <span class="o">/</span> <span class="n">gcd</span><span class="p">(</span><span class="n">n1</span><span class="p">,</span> <span class="n">n2</span><span class="p">)</span>

        <span class="c1"># assumes all order parameters for a given species are the same</span>
        <span class="n">mag_species_order_parameter</span> <span class="o">=</span> <span class="p">{}</span>
        <span class="n">mag_species_occurrences</span> <span class="o">=</span> <span class="p">{}</span>
        <span class="k">for</span> <span class="n">idx</span><span class="p">,</span> <span class="n">site</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="n">disordered_structure</span><span class="p">):</span>
            <span class="k">if</span> <span class="ow">not</span> <span class="n">site</span><span class="o">.</span><span class="n">is_ordered</span><span class="p">:</span>
                <span class="n">op</span> <span class="o">=</span> <span class="nb">max</span><span class="p">(</span><span class="n">site</span><span class="o">.</span><span class="n">species</span><span class="o">.</span><span class="n">values</span><span class="p">())</span>
                <span class="c1"># this very hacky bit of code only works because we know</span>
                <span class="c1"># that on disordered sites in this class, all species are the same</span>
                <span class="c1"># but have different spins, and this is comma-delimited</span>
                <span class="n">sp</span> <span class="o">=</span> <span class="nb">str</span><span class="p">(</span><span class="nb">list</span><span class="p">(</span><span class="n">site</span><span class="o">.</span><span class="n">species</span><span class="o">.</span><span class="n">keys</span><span class="p">())[</span><span class="mi">0</span><span class="p">])</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s2">&quot;,&quot;</span><span class="p">)[</span><span class="mi">0</span><span class="p">]</span>
                <span class="k">if</span> <span class="n">sp</span> <span class="ow">in</span> <span class="n">mag_species_order_parameter</span><span class="p">:</span>
                    <span class="n">mag_species_occurrences</span><span class="p">[</span><span class="n">sp</span><span class="p">]</span> <span class="o">+=</span> <span class="mi">1</span>
                <span class="k">else</span><span class="p">:</span>
                    <span class="n">mag_species_order_parameter</span><span class="p">[</span><span class="n">sp</span><span class="p">]</span> <span class="o">=</span> <span class="n">op</span>
                    <span class="n">mag_species_occurrences</span><span class="p">[</span><span class="n">sp</span><span class="p">]</span> <span class="o">=</span> <span class="mi">1</span>

        <span class="n">smallest_n</span> <span class="o">=</span> <span class="p">[]</span>

        <span class="k">for</span> <span class="n">sp</span><span class="p">,</span> <span class="n">order_parameter</span> <span class="ow">in</span> <span class="n">mag_species_order_parameter</span><span class="o">.</span><span class="n">items</span><span class="p">():</span>
            <span class="n">denom</span> <span class="o">=</span> <span class="n">Fraction</span><span class="p">(</span><span class="n">order_parameter</span><span class="p">)</span><span class="o">.</span><span class="n">limit_denominator</span><span class="p">(</span><span class="mi">100</span><span class="p">)</span><span class="o">.</span><span class="n">denominator</span>
            <span class="n">num_atom_per_specie</span> <span class="o">=</span> <span class="n">mag_species_occurrences</span><span class="p">[</span><span class="n">sp</span><span class="p">]</span>
            <span class="n">n_gcd</span> <span class="o">=</span> <span class="n">gcd</span><span class="p">(</span><span class="n">denom</span><span class="p">,</span> <span class="n">num_atom_per_specie</span><span class="p">)</span>
            <span class="n">smallest_n</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">lcm</span><span class="p">(</span><span class="nb">int</span><span class="p">(</span><span class="n">n_gcd</span><span class="p">),</span> <span class="n">denom</span><span class="p">)</span> <span class="o">/</span> <span class="n">n_gcd</span><span class="p">)</span>

        <span class="k">return</span> <span class="nb">max</span><span class="p">(</span><span class="n">smallest_n</span><span class="p">)</span></div>

    <span class="nd">@staticmethod</span>
    <span class="k">def</span> <span class="nf">_add_dummy_species</span><span class="p">(</span><span class="n">structure</span><span class="p">,</span> <span class="n">order_parameters</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        :param structure: ordered Structure</span>
<span class="sd">        :param order_parameters: list of MagOrderParameterConstraints</span>
<span class="sd">        :return: A structure decorated with disordered</span>
<span class="sd">            DummySpecies on which to perform the enumeration.</span>
<span class="sd">            Note that the DummySpecies are super-imposed on</span>
<span class="sd">            to the original sites, to make it easier to</span>
<span class="sd">            retrieve the original site after enumeration is</span>
<span class="sd">            performed (this approach is preferred over a simple</span>
<span class="sd">            mapping since multiple species may have the same</span>
<span class="sd">            DummySpecie, depending on the constraints specified).</span>
<span class="sd">            This approach can also preserve site properties even after</span>
<span class="sd">            enumeration.</span>
<span class="sd">        &quot;&quot;&quot;</span>

        <span class="n">dummy_struct</span> <span class="o">=</span> <span class="n">structure</span><span class="o">.</span><span class="n">copy</span><span class="p">()</span>

        <span class="k">def</span> <span class="nf">generate_dummy_specie</span><span class="p">():</span>
            <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">            Generator which returns DummySpecie symbols Mma, Mmb, etc.</span>
<span class="sd">            &quot;&quot;&quot;</span>
            <span class="n">subscript_length</span> <span class="o">=</span> <span class="mi">1</span>
            <span class="k">while</span> <span class="kc">True</span><span class="p">:</span>
                <span class="k">for</span> <span class="n">subscript</span> <span class="ow">in</span> <span class="n">product</span><span class="p">(</span><span class="n">ascii_lowercase</span><span class="p">,</span> <span class="n">repeat</span><span class="o">=</span><span class="n">subscript_length</span><span class="p">):</span>
                    <span class="k">yield</span> <span class="s2">&quot;Mm&quot;</span> <span class="o">+</span> <span class="s2">&quot;&quot;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">subscript</span><span class="p">)</span>
                <span class="n">subscript_length</span> <span class="o">+=</span> <span class="mi">1</span>

        <span class="n">dummy_species_gen</span> <span class="o">=</span> <span class="n">generate_dummy_specie</span><span class="p">()</span>

        <span class="c1"># one dummy species for each order parameter constraint</span>
        <span class="n">dummy_species_symbols</span> <span class="o">=</span> <span class="p">[</span>
            <span class="nb">next</span><span class="p">(</span><span class="n">dummy_species_gen</span><span class="p">)</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">order_parameters</span><span class="p">))</span>
        <span class="p">]</span>
        <span class="n">dummy_species</span> <span class="o">=</span> <span class="p">[</span>
            <span class="p">{</span>
                <span class="n">DummySpecie</span><span class="p">(</span>
                    <span class="n">symbol</span><span class="p">,</span> <span class="n">properties</span><span class="o">=</span><span class="p">{</span><span class="s2">&quot;spin&quot;</span><span class="p">:</span> <span class="n">Spin</span><span class="o">.</span><span class="n">up</span><span class="p">}</span>
                <span class="p">):</span> <span class="n">constraint</span><span class="o">.</span><span class="n">order_parameter</span><span class="p">,</span>
                <span class="n">DummySpecie</span><span class="p">(</span><span class="n">symbol</span><span class="p">,</span> <span class="n">properties</span><span class="o">=</span><span class="p">{</span><span class="s2">&quot;spin&quot;</span><span class="p">:</span> <span class="n">Spin</span><span class="o">.</span><span class="n">down</span><span class="p">}):</span> <span class="mi">1</span>
                <span class="o">-</span> <span class="n">constraint</span><span class="o">.</span><span class="n">order_parameter</span><span class="p">,</span>
            <span class="p">}</span>
            <span class="k">for</span> <span class="n">symbol</span><span class="p">,</span> <span class="n">constraint</span> <span class="ow">in</span> <span class="nb">zip</span><span class="p">(</span><span class="n">dummy_species_symbols</span><span class="p">,</span> <span class="n">order_parameters</span><span class="p">)</span>
        <span class="p">]</span>

        <span class="k">for</span> <span class="n">idx</span><span class="p">,</span> <span class="n">site</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="n">dummy_struct</span><span class="p">):</span>
            <span class="n">satisfies_constraints</span> <span class="o">=</span> <span class="p">[</span>
                <span class="n">c</span><span class="o">.</span><span class="n">satisfies_constraint</span><span class="p">(</span><span class="n">site</span><span class="p">)</span> <span class="k">for</span> <span class="n">c</span> <span class="ow">in</span> <span class="n">order_parameters</span>
            <span class="p">]</span>
            <span class="k">if</span> <span class="n">satisfies_constraints</span><span class="o">.</span><span class="n">count</span><span class="p">(</span><span class="kc">True</span><span class="p">)</span> <span class="o">&gt;</span> <span class="mi">1</span><span class="p">:</span>
                <span class="c1"># site should either not satisfy any constraints, or satisfy</span>
                <span class="c1"># one constraint</span>
                <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span>
                    <span class="s2">&quot;Order parameter constraints conflict for site: </span><span class="si">{}</span><span class="s2">, </span><span class="si">{}</span><span class="s2">&quot;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span>
                        <span class="nb">str</span><span class="p">(</span><span class="n">site</span><span class="o">.</span><span class="n">specie</span><span class="p">),</span> <span class="n">site</span><span class="o">.</span><span class="n">properties</span>
                    <span class="p">)</span>
                <span class="p">)</span>
            <span class="k">elif</span> <span class="nb">any</span><span class="p">(</span><span class="n">satisfies_constraints</span><span class="p">):</span>
                <span class="n">dummy_specie_idx</span> <span class="o">=</span> <span class="n">satisfies_constraints</span><span class="o">.</span><span class="n">index</span><span class="p">(</span><span class="kc">True</span><span class="p">)</span>
                <span class="n">dummy_struct</span><span class="o">.</span><span class="n">append</span><span class="p">(</span>
                    <span class="n">dummy_species</span><span class="p">[</span><span class="n">dummy_specie_idx</span><span class="p">],</span> <span class="n">site</span><span class="o">.</span><span class="n">coords</span><span class="p">,</span> <span class="n">site</span><span class="o">.</span><span class="n">lattice</span>
                <span class="p">)</span>

        <span class="k">return</span> <span class="n">dummy_struct</span>

    <span class="nd">@staticmethod</span>
    <span class="k">def</span> <span class="nf">_remove_dummy_species</span><span class="p">(</span><span class="n">structure</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        :return: Structure with dummy species removed, but</span>
<span class="sd">        their corresponding spin properties merged with the</span>
<span class="sd">        original sites. Used after performing enumeration.</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="k">if</span> <span class="ow">not</span> <span class="n">structure</span><span class="o">.</span><span class="n">is_ordered</span><span class="p">:</span>
            <span class="k">raise</span> <span class="ne">Exception</span><span class="p">(</span><span class="s2">&quot;Something went wrong with enumeration.&quot;</span><span class="p">)</span>

        <span class="n">sites_to_remove</span> <span class="o">=</span> <span class="p">[]</span>
        <span class="n">logger</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="s2">&quot;Dummy species structure:</span><span class="se">\n</span><span class="si">{}</span><span class="s2">&quot;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">structure</span><span class="p">)))</span>
        <span class="k">for</span> <span class="n">idx</span><span class="p">,</span> <span class="n">site</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="n">structure</span><span class="p">):</span>
            <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">site</span><span class="o">.</span><span class="n">specie</span><span class="p">,</span> <span class="n">DummySpecie</span><span class="p">):</span>
                <span class="n">sites_to_remove</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">idx</span><span class="p">)</span>
                <span class="n">spin</span> <span class="o">=</span> <span class="n">site</span><span class="o">.</span><span class="n">specie</span><span class="o">.</span><span class="n">_properties</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;spin&quot;</span><span class="p">,</span> <span class="kc">None</span><span class="p">)</span>
                <span class="n">neighbors</span> <span class="o">=</span> <span class="n">structure</span><span class="o">.</span><span class="n">get_neighbors</span><span class="p">(</span>
                    <span class="n">site</span><span class="p">,</span>
                    <span class="mf">0.05</span><span class="p">,</span>  <span class="c1"># arbitrary threshold, needs to be &lt;&lt; any bond length</span>
                    <span class="c1"># but &gt;&gt; floating point precision issues</span>
                    <span class="n">include_index</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span>
                <span class="p">)</span>
                <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">neighbors</span><span class="p">)</span> <span class="o">!=</span> <span class="mi">1</span><span class="p">:</span>
                    <span class="k">raise</span> <span class="ne">Exception</span><span class="p">(</span>
                        <span class="s2">&quot;This shouldn&#39;t happen, found neighbors: </span><span class="si">{}</span><span class="s2">&quot;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">neighbors</span><span class="p">)</span>
                    <span class="p">)</span>
                <span class="n">orig_site_idx</span> <span class="o">=</span> <span class="n">neighbors</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="mi">2</span><span class="p">]</span>
                <span class="n">orig_specie</span> <span class="o">=</span> <span class="n">structure</span><span class="p">[</span><span class="n">orig_site_idx</span><span class="p">]</span><span class="o">.</span><span class="n">specie</span>
                <span class="n">new_specie</span> <span class="o">=</span> <span class="n">Specie</span><span class="p">(</span>
                    <span class="n">orig_specie</span><span class="o">.</span><span class="n">symbol</span><span class="p">,</span>
                    <span class="nb">getattr</span><span class="p">(</span><span class="n">orig_specie</span><span class="p">,</span> <span class="s2">&quot;oxi_state&quot;</span><span class="p">,</span> <span class="kc">None</span><span class="p">),</span>
                    <span class="n">properties</span><span class="o">=</span><span class="p">{</span><span class="s2">&quot;spin&quot;</span><span class="p">:</span> <span class="n">spin</span><span class="p">},</span>
                <span class="p">)</span>
                <span class="n">structure</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span>
                    <span class="n">orig_site_idx</span><span class="p">,</span>
                    <span class="n">new_specie</span><span class="p">,</span>
                    <span class="n">properties</span><span class="o">=</span><span class="n">structure</span><span class="p">[</span><span class="n">orig_site_idx</span><span class="p">]</span><span class="o">.</span><span class="n">properties</span><span class="p">,</span>
                <span class="p">)</span>
        <span class="n">structure</span><span class="o">.</span><span class="n">remove_sites</span><span class="p">(</span><span class="n">sites_to_remove</span><span class="p">)</span>
        <span class="n">logger</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="s2">&quot;Structure with dummy species removed:</span><span class="se">\n</span><span class="si">{}</span><span class="s2">&quot;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">structure</span><span class="p">)))</span>
        <span class="k">return</span> <span class="n">structure</span>

    <span class="k">def</span> <span class="nf">_add_spin_magnitudes</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">structure</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Replaces Spin.up/Spin.down with spin magnitudes specified</span>
<span class="sd">        by mag_species_spin.</span>
<span class="sd">        :param structure:</span>
<span class="sd">        :return:</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="k">for</span> <span class="n">idx</span><span class="p">,</span> <span class="n">site</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="n">structure</span><span class="p">):</span>
            <span class="k">if</span> <span class="nb">getattr</span><span class="p">(</span><span class="n">site</span><span class="o">.</span><span class="n">specie</span><span class="p">,</span> <span class="s2">&quot;_properties&quot;</span><span class="p">,</span> <span class="kc">None</span><span class="p">):</span>
                <span class="n">spin</span> <span class="o">=</span> <span class="n">site</span><span class="o">.</span><span class="n">specie</span><span class="o">.</span><span class="n">_properties</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;spin&quot;</span><span class="p">,</span> <span class="kc">None</span><span class="p">)</span>
                <span class="n">sign</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">spin</span><span class="p">)</span> <span class="k">if</span> <span class="n">spin</span> <span class="k">else</span> <span class="mi">0</span>
                <span class="k">if</span> <span class="n">spin</span><span class="p">:</span>
                    <span class="n">new_properties</span> <span class="o">=</span> <span class="n">site</span><span class="o">.</span><span class="n">specie</span><span class="o">.</span><span class="n">_properties</span><span class="o">.</span><span class="n">copy</span><span class="p">()</span>
                    <span class="c1"># this very hacky bit of code only works because we know</span>
                    <span class="c1"># that on disordered sites in this class, all species are the same</span>
                    <span class="c1"># but have different spins, and this is comma-delimited</span>
                    <span class="n">sp</span> <span class="o">=</span> <span class="nb">str</span><span class="p">(</span><span class="n">site</span><span class="o">.</span><span class="n">specie</span><span class="p">)</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s2">&quot;,&quot;</span><span class="p">)[</span><span class="mi">0</span><span class="p">]</span>
                    <span class="n">new_properties</span><span class="o">.</span><span class="n">update</span><span class="p">(</span>
                        <span class="p">{</span><span class="s2">&quot;spin&quot;</span><span class="p">:</span> <span class="n">sign</span> <span class="o">*</span> <span class="bp">self</span><span class="o">.</span><span class="n">mag_species_spin</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">sp</span><span class="p">,</span> <span class="mi">0</span><span class="p">)}</span>
                    <span class="p">)</span>
                    <span class="n">new_specie</span> <span class="o">=</span> <span class="n">Specie</span><span class="p">(</span>
                        <span class="n">site</span><span class="o">.</span><span class="n">specie</span><span class="o">.</span><span class="n">symbol</span><span class="p">,</span>
                        <span class="nb">getattr</span><span class="p">(</span><span class="n">site</span><span class="o">.</span><span class="n">specie</span><span class="p">,</span> <span class="s2">&quot;oxi_state&quot;</span><span class="p">,</span> <span class="kc">None</span><span class="p">),</span>
                        <span class="n">new_properties</span><span class="p">,</span>
                    <span class="p">)</span>
                    <span class="n">structure</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="n">idx</span><span class="p">,</span> <span class="n">new_specie</span><span class="p">,</span> <span class="n">properties</span><span class="o">=</span><span class="n">site</span><span class="o">.</span><span class="n">properties</span><span class="p">)</span>
        <span class="n">logger</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="s2">&quot;Structure with spin magnitudes:</span><span class="se">\n</span><span class="si">{}</span><span class="s2">&quot;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">structure</span><span class="p">)))</span>
        <span class="k">return</span> <span class="n">structure</span>

<div class="viewcode-block" id="MagOrderingTransformation.apply_transformation"><a class="viewcode-back" href="../../../pymatgen.transformations.advanced_transformations.html#pymatgen.transformations.advanced_transformations.MagOrderingTransformation.apply_transformation">[docs]</a>    <span class="k">def</span> <span class="nf">apply_transformation</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">structure</span><span class="p">,</span> <span class="n">return_ranked_list</span><span class="o">=</span><span class="kc">False</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Apply MagOrderTransformation to an input structure.</span>
<span class="sd">        :param structure: Any ordered structure.</span>
<span class="sd">        :param return_ranked_list: As in other Transformations.</span>
<span class="sd">        :return:</span>
<span class="sd">        &quot;&quot;&quot;</span>

        <span class="k">if</span> <span class="ow">not</span> <span class="n">structure</span><span class="o">.</span><span class="n">is_ordered</span><span class="p">:</span>
            <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span>
                <span class="s2">&quot;Create an ordered approximation of &quot;</span> <span class="s2">&quot;your  input structure first.&quot;</span>
            <span class="p">)</span>

        <span class="c1"># retrieve order parameters</span>
        <span class="n">order_parameters</span> <span class="o">=</span> <span class="p">[</span>
            <span class="n">MagOrderParameterConstraint</span><span class="o">.</span><span class="n">from_dict</span><span class="p">(</span><span class="n">op_dict</span><span class="p">)</span>
            <span class="k">for</span> <span class="n">op_dict</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">order_parameter</span>
        <span class="p">]</span>
        <span class="c1"># add dummy species on which to perform enumeration</span>
        <span class="n">structure</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_add_dummy_species</span><span class="p">(</span><span class="n">structure</span><span class="p">,</span> <span class="n">order_parameters</span><span class="p">)</span>

        <span class="c1"># trivial case</span>
        <span class="k">if</span> <span class="n">structure</span><span class="o">.</span><span class="n">is_ordered</span><span class="p">:</span>
            <span class="n">structure</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_remove_dummy_species</span><span class="p">(</span><span class="n">structure</span><span class="p">)</span>
            <span class="k">return</span> <span class="p">[</span><span class="n">structure</span><span class="p">]</span> <span class="k">if</span> <span class="n">return_ranked_list</span> <span class="o">&gt;</span> <span class="mi">1</span> <span class="k">else</span> <span class="n">structure</span>

        <span class="n">enum_kwargs</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">enum_kwargs</span><span class="o">.</span><span class="n">copy</span><span class="p">()</span>

        <span class="n">enum_kwargs</span><span class="p">[</span><span class="s2">&quot;min_cell_size&quot;</span><span class="p">]</span> <span class="o">=</span> <span class="nb">max</span><span class="p">(</span>
            <span class="nb">int</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">determine_min_cell</span><span class="p">(</span><span class="n">structure</span><span class="p">)),</span> <span class="n">enum_kwargs</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;min_cell_size&quot;</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
        <span class="p">)</span>

        <span class="k">if</span> <span class="n">enum_kwargs</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;max_cell_size&quot;</span><span class="p">,</span> <span class="kc">None</span><span class="p">):</span>
            <span class="k">if</span> <span class="n">enum_kwargs</span><span class="p">[</span><span class="s2">&quot;min_cell_size&quot;</span><span class="p">]</span> <span class="o">&gt;</span> <span class="n">enum_kwargs</span><span class="p">[</span><span class="s2">&quot;max_cell_size&quot;</span><span class="p">]:</span>
                <span class="n">warnings</span><span class="o">.</span><span class="n">warn</span><span class="p">(</span>
                    <span class="s2">&quot;Specified max cell size (</span><span class="si">{}</span><span class="s2">) is smaller &quot;</span>
                    <span class="s2">&quot;than the minimum enumerable cell size (</span><span class="si">{}</span><span class="s2">), &quot;</span>
                    <span class="s2">&quot;changing max cell size to </span><span class="si">{}</span><span class="s2">&quot;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span>
                        <span class="n">enum_kwargs</span><span class="p">[</span><span class="s2">&quot;max_cell_size&quot;</span><span class="p">],</span>
                        <span class="n">enum_kwargs</span><span class="p">[</span><span class="s2">&quot;min_cell_size&quot;</span><span class="p">],</span>
                        <span class="n">enum_kwargs</span><span class="p">[</span><span class="s2">&quot;min_cell_size&quot;</span><span class="p">],</span>
                    <span class="p">)</span>
                <span class="p">)</span>
                <span class="n">enum_kwargs</span><span class="p">[</span><span class="s2">&quot;max_cell_size&quot;</span><span class="p">]</span> <span class="o">=</span> <span class="n">enum_kwargs</span><span class="p">[</span><span class="s2">&quot;min_cell_size&quot;</span><span class="p">]</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="n">enum_kwargs</span><span class="p">[</span><span class="s2">&quot;max_cell_size&quot;</span><span class="p">]</span> <span class="o">=</span> <span class="n">enum_kwargs</span><span class="p">[</span><span class="s2">&quot;min_cell_size&quot;</span><span class="p">]</span>

        <span class="n">t</span> <span class="o">=</span> <span class="n">EnumerateStructureTransformation</span><span class="p">(</span><span class="o">**</span><span class="n">enum_kwargs</span><span class="p">)</span>

        <span class="n">alls</span> <span class="o">=</span> <span class="n">t</span><span class="o">.</span><span class="n">apply_transformation</span><span class="p">(</span><span class="n">structure</span><span class="p">,</span> <span class="n">return_ranked_list</span><span class="o">=</span><span class="n">return_ranked_list</span><span class="p">)</span>

        <span class="c1"># handle the fact that EnumerateStructureTransformation can either</span>
        <span class="c1"># return a single Structure or a list</span>
        <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">alls</span><span class="p">,</span> <span class="n">Structure</span><span class="p">):</span>
            <span class="c1"># remove dummy species and replace Spin.up or Spin.down</span>
            <span class="c1"># with spin magnitudes given in mag_species_spin arg</span>
            <span class="n">alls</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_remove_dummy_species</span><span class="p">(</span><span class="n">alls</span><span class="p">)</span>
            <span class="n">alls</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_add_spin_magnitudes</span><span class="p">(</span><span class="n">alls</span><span class="p">)</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="k">for</span> <span class="n">idx</span><span class="p">,</span> <span class="n">_</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="n">alls</span><span class="p">):</span>
                <span class="n">alls</span><span class="p">[</span><span class="n">idx</span><span class="p">][</span><span class="s2">&quot;structure&quot;</span><span class="p">]</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_remove_dummy_species</span><span class="p">(</span>
                    <span class="n">alls</span><span class="p">[</span><span class="n">idx</span><span class="p">][</span><span class="s2">&quot;structure&quot;</span><span class="p">]</span>
                <span class="p">)</span>
                <span class="n">alls</span><span class="p">[</span><span class="n">idx</span><span class="p">][</span><span class="s2">&quot;structure&quot;</span><span class="p">]</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_add_spin_magnitudes</span><span class="p">(</span>
                    <span class="n">alls</span><span class="p">[</span><span class="n">idx</span><span class="p">][</span><span class="s2">&quot;structure&quot;</span><span class="p">]</span>
                <span class="p">)</span>

        <span class="k">try</span><span class="p">:</span>
            <span class="n">num_to_return</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">return_ranked_list</span><span class="p">)</span>
        <span class="k">except</span> <span class="ne">ValueError</span><span class="p">:</span>
            <span class="n">num_to_return</span> <span class="o">=</span> <span class="mi">1</span>

        <span class="k">if</span> <span class="n">num_to_return</span> <span class="o">==</span> <span class="mi">1</span> <span class="ow">or</span> <span class="ow">not</span> <span class="n">return_ranked_list</span><span class="p">:</span>
            <span class="k">return</span> <span class="n">alls</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="s2">&quot;structure&quot;</span><span class="p">]</span> <span class="k">if</span> <span class="n">num_to_return</span> <span class="k">else</span> <span class="n">alls</span>

        <span class="c1"># remove duplicate structures and group according to energy model</span>
        <span class="n">m</span> <span class="o">=</span> <span class="n">StructureMatcher</span><span class="p">(</span><span class="n">comparator</span><span class="o">=</span><span class="n">SpinComparator</span><span class="p">())</span>

        <span class="k">def</span> <span class="nf">key</span><span class="p">(</span><span class="n">x</span><span class="p">):</span>
            <span class="k">return</span> <span class="n">SpacegroupAnalyzer</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="mf">0.1</span><span class="p">)</span><span class="o">.</span><span class="n">get_space_group_number</span><span class="p">()</span>

        <span class="n">out</span> <span class="o">=</span> <span class="p">[]</span>
        <span class="k">for</span> <span class="n">_</span><span class="p">,</span> <span class="n">g</span> <span class="ow">in</span> <span class="n">groupby</span><span class="p">(</span><span class="nb">sorted</span><span class="p">([</span><span class="n">d</span><span class="p">[</span><span class="s2">&quot;structure&quot;</span><span class="p">]</span> <span class="k">for</span> <span class="n">d</span> <span class="ow">in</span> <span class="n">alls</span><span class="p">],</span> <span class="n">key</span><span class="o">=</span><span class="n">key</span><span class="p">),</span> <span class="n">key</span><span class="p">):</span>
            <span class="n">g</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="n">g</span><span class="p">)</span>
            <span class="n">grouped</span> <span class="o">=</span> <span class="n">m</span><span class="o">.</span><span class="n">group_structures</span><span class="p">(</span><span class="n">g</span><span class="p">)</span>
            <span class="n">out</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span>
                <span class="p">[</span>
                    <span class="p">{</span><span class="s2">&quot;structure&quot;</span><span class="p">:</span> <span class="n">g</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="s2">&quot;energy&quot;</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">energy_model</span><span class="o">.</span><span class="n">get_energy</span><span class="p">(</span><span class="n">g</span><span class="p">[</span><span class="mi">0</span><span class="p">])}</span>
                    <span class="k">for</span> <span class="n">g</span> <span class="ow">in</span> <span class="n">grouped</span>
                <span class="p">]</span>
            <span class="p">)</span>

        <span class="bp">self</span><span class="o">.</span><span class="n">_all_structures</span> <span class="o">=</span> <span class="nb">sorted</span><span class="p">(</span><span class="n">out</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="k">lambda</span> <span class="n">d</span><span class="p">:</span> <span class="n">d</span><span class="p">[</span><span class="s2">&quot;energy&quot;</span><span class="p">])</span>

        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_all_structures</span><span class="p">[</span><span class="mi">0</span><span class="p">:</span><span class="n">num_to_return</span><span class="p">]</span></div>

    <span class="k">def</span> <span class="fm">__str__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="k">return</span> <span class="s2">&quot;MagOrderingTransformation&quot;</span>

    <span class="k">def</span> <span class="fm">__repr__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="fm">__str__</span><span class="p">()</span>

    <span class="nd">@property</span>
    <span class="k">def</span> <span class="nf">inverse</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;Returns: None&quot;&quot;&quot;</span>
        <span class="k">return</span> <span class="kc">None</span>

    <span class="nd">@property</span>
    <span class="k">def</span> <span class="nf">is_one_to_many</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;Returns: True&quot;&quot;&quot;</span>
        <span class="k">return</span> <span class="kc">True</span></div>


<span class="k">def</span> <span class="nf">_find_codopant</span><span class="p">(</span><span class="n">target</span><span class="p">,</span> <span class="n">oxidation_state</span><span class="p">,</span> <span class="n">allowed_elements</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    Finds the element from &quot;allowed elements&quot; that (i) possesses the desired</span>
<span class="sd">    &quot;oxidation state&quot; and (ii) is closest in ionic radius to the target specie</span>

<span class="sd">    Args:</span>
<span class="sd">        target: (Specie) provides target ionic radius.</span>
<span class="sd">        oxidation_state: (float) codopant oxidation state.</span>
<span class="sd">        allowed_elements: ([str]) List of allowed elements. If None,</span>
<span class="sd">            all elements are tried.</span>

<span class="sd">    Returns:</span>
<span class="sd">        (Specie) with oxidation_state that has ionic radius closest to</span>
<span class="sd">        target.</span>
<span class="sd">    &quot;&quot;&quot;</span>
    <span class="n">ref_radius</span> <span class="o">=</span> <span class="n">target</span><span class="o">.</span><span class="n">ionic_radius</span>
    <span class="n">candidates</span> <span class="o">=</span> <span class="p">[]</span>
    <span class="n">symbols</span> <span class="o">=</span> <span class="n">allowed_elements</span> <span class="ow">or</span> <span class="p">[</span><span class="n">el</span><span class="o">.</span><span class="n">symbol</span> <span class="k">for</span> <span class="n">el</span> <span class="ow">in</span> <span class="n">Element</span><span class="p">]</span>
    <span class="k">for</span> <span class="n">sym</span> <span class="ow">in</span> <span class="n">symbols</span><span class="p">:</span>
        <span class="k">try</span><span class="p">:</span>
            <span class="k">with</span> <span class="n">warnings</span><span class="o">.</span><span class="n">catch_warnings</span><span class="p">():</span>
                <span class="n">warnings</span><span class="o">.</span><span class="n">simplefilter</span><span class="p">(</span><span class="s2">&quot;ignore&quot;</span><span class="p">)</span>
                <span class="n">sp</span> <span class="o">=</span> <span class="n">Specie</span><span class="p">(</span><span class="n">sym</span><span class="p">,</span> <span class="n">oxidation_state</span><span class="p">)</span>
                <span class="n">r</span> <span class="o">=</span> <span class="n">sp</span><span class="o">.</span><span class="n">ionic_radius</span>
                <span class="k">if</span> <span class="n">r</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
                    <span class="n">candidates</span><span class="o">.</span><span class="n">append</span><span class="p">((</span><span class="n">r</span><span class="p">,</span> <span class="n">sp</span><span class="p">))</span>
        <span class="k">except</span> <span class="ne">Exception</span><span class="p">:</span>
            <span class="k">pass</span>
    <span class="k">return</span> <span class="nb">min</span><span class="p">(</span><span class="n">candidates</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="k">lambda</span> <span class="n">l</span><span class="p">:</span> <span class="nb">abs</span><span class="p">(</span><span class="n">l</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">/</span> <span class="n">ref_radius</span> <span class="o">-</span> <span class="mi">1</span><span class="p">))[</span><span class="mi">1</span><span class="p">]</span>


<div class="viewcode-block" id="DopingTransformation"><a class="viewcode-back" href="../../../pymatgen.transformations.advanced_transformations.html#pymatgen.transformations.advanced_transformations.DopingTransformation">[docs]</a><span class="k">class</span> <span class="nc">DopingTransformation</span><span class="p">(</span><span class="n">AbstractTransformation</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    A transformation that performs doping of a structure.</span>
<span class="sd">    &quot;&quot;&quot;</span>

    <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span>
        <span class="bp">self</span><span class="p">,</span>
        <span class="n">dopant</span><span class="p">,</span>
        <span class="n">ionic_radius_tol</span><span class="o">=</span><span class="nb">float</span><span class="p">(</span><span class="s2">&quot;inf&quot;</span><span class="p">),</span>
        <span class="n">min_length</span><span class="o">=</span><span class="mi">10</span><span class="p">,</span>
        <span class="n">alio_tol</span><span class="o">=</span><span class="mi">0</span><span class="p">,</span>
        <span class="n">codopant</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span>
        <span class="n">max_structures_per_enum</span><span class="o">=</span><span class="mi">100</span><span class="p">,</span>
        <span class="n">allowed_doping_species</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
        <span class="o">**</span><span class="n">kwargs</span>
    <span class="p">):</span>
        <span class="sa">r</span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Args:</span>
<span class="sd">            dopant (Specie-like): E.g., Al3+. Must have oxidation state.</span>
<span class="sd">            ionic_radius_tol (float): E.g., Fractional allowable ionic radii</span>
<span class="sd">                mismatch for dopant to fit into a site. Default of inf means</span>
<span class="sd">                that any dopant with the right oxidation state is allowed.</span>
<span class="sd">            min_Length (float): Min. lattice parameter between periodic</span>
<span class="sd">                images of dopant. Defaults to 10A for now.</span>
<span class="sd">            alio_tol (int): If this is not 0, attempt will be made to dope</span>
<span class="sd">                sites with oxidation_states +- alio_tol of the dopant. E.g.,</span>
<span class="sd">                1 means that the ions like Ca2+ and Ti4+ are considered as</span>
<span class="sd">                potential doping sites for Al3+.</span>
<span class="sd">            codopant (bool): If True, doping will be carried out with a</span>
<span class="sd">                codopant to maintain charge neutrality. Otherwise, vacancies</span>
<span class="sd">                will be used.</span>
<span class="sd">            max_structures_per_enum (float): Maximum number of structures to</span>
<span class="sd">                return per enumeration. Note that there can be more than one</span>
<span class="sd">                candidate doping site, and each site enumeration will return at</span>
<span class="sd">                max max_structures_per_enum structures. Defaults to 100.</span>
<span class="sd">            allowed_doping_species (list): Species that are allowed to be</span>
<span class="sd">                doping sites. This is an inclusionary list. If specified,</span>
<span class="sd">                any sites which are not</span>
<span class="sd">            **kwargs:</span>
<span class="sd">                Same keyword args as :class:`EnumerateStructureTransformation`,</span>
<span class="sd">                i.e., min_cell_size, etc.</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">dopant</span> <span class="o">=</span> <span class="n">get_el_sp</span><span class="p">(</span><span class="n">dopant</span><span class="p">)</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">ionic_radius_tol</span> <span class="o">=</span> <span class="n">ionic_radius_tol</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">min_length</span> <span class="o">=</span> <span class="n">min_length</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">alio_tol</span> <span class="o">=</span> <span class="n">alio_tol</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">codopant</span> <span class="o">=</span> <span class="n">codopant</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">max_structures_per_enum</span> <span class="o">=</span> <span class="n">max_structures_per_enum</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">allowed_doping_species</span> <span class="o">=</span> <span class="n">allowed_doping_species</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">kwargs</span> <span class="o">=</span> <span class="n">kwargs</span>

<div class="viewcode-block" id="DopingTransformation.apply_transformation"><a class="viewcode-back" href="../../../pymatgen.transformations.advanced_transformations.html#pymatgen.transformations.advanced_transformations.DopingTransformation.apply_transformation">[docs]</a>    <span class="k">def</span> <span class="nf">apply_transformation</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">structure</span><span class="p">,</span> <span class="n">return_ranked_list</span><span class="o">=</span><span class="kc">False</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Args:</span>
<span class="sd">            structure (Structure): Input structure to dope</span>

<span class="sd">        Returns:</span>
<span class="sd">            [{&quot;structure&quot;: Structure, &quot;energy&quot;: float}]</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="n">comp</span> <span class="o">=</span> <span class="n">structure</span><span class="o">.</span><span class="n">composition</span>
        <span class="n">logger</span><span class="o">.</span><span class="n">info</span><span class="p">(</span><span class="s2">&quot;Composition: </span><span class="si">%s</span><span class="s2">&quot;</span> <span class="o">%</span> <span class="n">comp</span><span class="p">)</span>

        <span class="k">for</span> <span class="n">sp</span> <span class="ow">in</span> <span class="n">comp</span><span class="p">:</span>
            <span class="k">try</span><span class="p">:</span>
                <span class="n">sp</span><span class="o">.</span><span class="n">oxi_state</span>
            <span class="k">except</span> <span class="ne">AttributeError</span><span class="p">:</span>
                <span class="n">analyzer</span> <span class="o">=</span> <span class="n">BVAnalyzer</span><span class="p">()</span>
                <span class="n">structure</span> <span class="o">=</span> <span class="n">analyzer</span><span class="o">.</span><span class="n">get_oxi_state_decorated_structure</span><span class="p">(</span><span class="n">structure</span><span class="p">)</span>
                <span class="n">comp</span> <span class="o">=</span> <span class="n">structure</span><span class="o">.</span><span class="n">composition</span>
                <span class="k">break</span>

        <span class="n">ox</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">dopant</span><span class="o">.</span><span class="n">oxi_state</span>
        <span class="n">radius</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">dopant</span><span class="o">.</span><span class="n">ionic_radius</span>

        <span class="n">compatible_species</span> <span class="o">=</span> <span class="p">[</span>
            <span class="n">sp</span>
            <span class="k">for</span> <span class="n">sp</span> <span class="ow">in</span> <span class="n">comp</span>
            <span class="k">if</span> <span class="n">sp</span><span class="o">.</span><span class="n">oxi_state</span> <span class="o">==</span> <span class="n">ox</span>
            <span class="ow">and</span> <span class="nb">abs</span><span class="p">(</span><span class="n">sp</span><span class="o">.</span><span class="n">ionic_radius</span> <span class="o">/</span> <span class="n">radius</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="o">&lt;</span> <span class="bp">self</span><span class="o">.</span><span class="n">ionic_radius_tol</span>
        <span class="p">]</span>

        <span class="k">if</span> <span class="p">(</span><span class="ow">not</span> <span class="n">compatible_species</span><span class="p">)</span> <span class="ow">and</span> <span class="bp">self</span><span class="o">.</span><span class="n">alio_tol</span><span class="p">:</span>
            <span class="c1"># We only consider aliovalent doping if there are no compatible</span>
            <span class="c1"># isovalent species.</span>
            <span class="n">compatible_species</span> <span class="o">=</span> <span class="p">[</span>
                <span class="n">sp</span>
                <span class="k">for</span> <span class="n">sp</span> <span class="ow">in</span> <span class="n">comp</span>
                <span class="k">if</span> <span class="nb">abs</span><span class="p">(</span><span class="n">sp</span><span class="o">.</span><span class="n">oxi_state</span> <span class="o">-</span> <span class="n">ox</span><span class="p">)</span> <span class="o">&lt;=</span> <span class="bp">self</span><span class="o">.</span><span class="n">alio_tol</span>
                <span class="ow">and</span> <span class="nb">abs</span><span class="p">(</span><span class="n">sp</span><span class="o">.</span><span class="n">ionic_radius</span> <span class="o">/</span> <span class="n">radius</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="o">&lt;</span> <span class="bp">self</span><span class="o">.</span><span class="n">ionic_radius_tol</span>
                <span class="ow">and</span> <span class="n">sp</span><span class="o">.</span><span class="n">oxi_state</span> <span class="o">*</span> <span class="n">ox</span> <span class="o">&gt;=</span> <span class="mi">0</span>
            <span class="p">]</span>

        <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">allowed_doping_species</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
            <span class="c1"># Only keep allowed doping species.</span>
            <span class="n">compatible_species</span> <span class="o">=</span> <span class="p">[</span>
                <span class="n">sp</span>
                <span class="k">for</span> <span class="n">sp</span> <span class="ow">in</span> <span class="n">compatible_species</span>
                <span class="k">if</span> <span class="n">sp</span> <span class="ow">in</span> <span class="p">[</span><span class="n">get_el_sp</span><span class="p">(</span><span class="n">s</span><span class="p">)</span> <span class="k">for</span> <span class="n">s</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">allowed_doping_species</span><span class="p">]</span>
            <span class="p">]</span>

        <span class="n">logger</span><span class="o">.</span><span class="n">info</span><span class="p">(</span><span class="s2">&quot;Compatible species: </span><span class="si">%s</span><span class="s2">&quot;</span> <span class="o">%</span> <span class="n">compatible_species</span><span class="p">)</span>

        <span class="n">lengths</span> <span class="o">=</span> <span class="n">structure</span><span class="o">.</span><span class="n">lattice</span><span class="o">.</span><span class="n">abc</span>
        <span class="n">scaling</span> <span class="o">=</span> <span class="p">[</span><span class="nb">max</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="nb">int</span><span class="p">(</span><span class="nb">round</span><span class="p">(</span><span class="n">math</span><span class="o">.</span><span class="n">ceil</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">min_length</span> <span class="o">/</span> <span class="n">x</span><span class="p">))))</span> <span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="n">lengths</span><span class="p">]</span>
        <span class="n">logger</span><span class="o">.</span><span class="n">info</span><span class="p">(</span><span class="s2">&quot;Lengths are </span><span class="si">%s</span><span class="s2">&quot;</span> <span class="o">%</span> <span class="nb">str</span><span class="p">(</span><span class="n">lengths</span><span class="p">))</span>
        <span class="n">logger</span><span class="o">.</span><span class="n">info</span><span class="p">(</span><span class="s2">&quot;Scaling = </span><span class="si">%s</span><span class="s2">&quot;</span> <span class="o">%</span> <span class="nb">str</span><span class="p">(</span><span class="n">scaling</span><span class="p">))</span>

        <span class="n">all_structures</span> <span class="o">=</span> <span class="p">[]</span>
        <span class="n">t</span> <span class="o">=</span> <span class="n">EnumerateStructureTransformation</span><span class="p">(</span><span class="o">**</span><span class="bp">self</span><span class="o">.</span><span class="n">kwargs</span><span class="p">)</span>

        <span class="k">for</span> <span class="n">sp</span> <span class="ow">in</span> <span class="n">compatible_species</span><span class="p">:</span>
            <span class="n">supercell</span> <span class="o">=</span> <span class="n">structure</span> <span class="o">*</span> <span class="n">scaling</span>
            <span class="n">nsp</span> <span class="o">=</span> <span class="n">supercell</span><span class="o">.</span><span class="n">composition</span><span class="p">[</span><span class="n">sp</span><span class="p">]</span>
            <span class="k">if</span> <span class="n">sp</span><span class="o">.</span><span class="n">oxi_state</span> <span class="o">==</span> <span class="n">ox</span><span class="p">:</span>
                <span class="n">supercell</span><span class="o">.</span><span class="n">replace_species</span><span class="p">(</span>
                    <span class="p">{</span><span class="n">sp</span><span class="p">:</span> <span class="p">{</span><span class="n">sp</span><span class="p">:</span> <span class="p">(</span><span class="n">nsp</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="o">/</span> <span class="n">nsp</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">dopant</span><span class="p">:</span> <span class="mi">1</span> <span class="o">/</span> <span class="n">nsp</span><span class="p">}}</span>
                <span class="p">)</span>
                <span class="n">logger</span><span class="o">.</span><span class="n">info</span><span class="p">(</span>
                    <span class="s2">&quot;Doping </span><span class="si">%s</span><span class="s2"> for </span><span class="si">%s</span><span class="s2"> at level </span><span class="si">%.3f</span><span class="s2">&quot;</span> <span class="o">%</span> <span class="p">(</span><span class="n">sp</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">dopant</span><span class="p">,</span> <span class="mi">1</span> <span class="o">/</span> <span class="n">nsp</span><span class="p">)</span>
                <span class="p">)</span>
            <span class="k">elif</span> <span class="bp">self</span><span class="o">.</span><span class="n">codopant</span><span class="p">:</span>
                <span class="n">codopant</span> <span class="o">=</span> <span class="n">_find_codopant</span><span class="p">(</span><span class="n">sp</span><span class="p">,</span> <span class="mi">2</span> <span class="o">*</span> <span class="n">sp</span><span class="o">.</span><span class="n">oxi_state</span> <span class="o">-</span> <span class="n">ox</span><span class="p">)</span>
                <span class="n">supercell</span><span class="o">.</span><span class="n">replace_species</span><span class="p">(</span>
                    <span class="p">{</span><span class="n">sp</span><span class="p">:</span> <span class="p">{</span><span class="n">sp</span><span class="p">:</span> <span class="p">(</span><span class="n">nsp</span> <span class="o">-</span> <span class="mi">2</span><span class="p">)</span> <span class="o">/</span> <span class="n">nsp</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">dopant</span><span class="p">:</span> <span class="mi">1</span> <span class="o">/</span> <span class="n">nsp</span><span class="p">,</span> <span class="n">codopant</span><span class="p">:</span> <span class="mi">1</span> <span class="o">/</span> <span class="n">nsp</span><span class="p">}}</span>
                <span class="p">)</span>
                <span class="n">logger</span><span class="o">.</span><span class="n">info</span><span class="p">(</span>
                    <span class="s2">&quot;Doping </span><span class="si">%s</span><span class="s2"> for </span><span class="si">%s</span><span class="s2"> + </span><span class="si">%s</span><span class="s2"> at level </span><span class="si">%.3f</span><span class="s2">&quot;</span>
                    <span class="o">%</span> <span class="p">(</span><span class="n">sp</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">dopant</span><span class="p">,</span> <span class="n">codopant</span><span class="p">,</span> <span class="mi">1</span> <span class="o">/</span> <span class="n">nsp</span><span class="p">)</span>
                <span class="p">)</span>
            <span class="k">elif</span> <span class="nb">abs</span><span class="p">(</span><span class="n">sp</span><span class="o">.</span><span class="n">oxi_state</span><span class="p">)</span> <span class="o">&lt;</span> <span class="nb">abs</span><span class="p">(</span><span class="n">ox</span><span class="p">):</span>
                <span class="c1"># Strategy: replace the target species with a</span>
                <span class="c1"># combination of dopant and vacancy.</span>
                <span class="c1"># We will choose the lowest oxidation state species as a</span>
                <span class="c1"># vacancy compensation species as it is likely to be lower in</span>
                <span class="c1"># energy</span>
                <span class="n">sp_to_remove</span> <span class="o">=</span> <span class="nb">min</span><span class="p">(</span>
                    <span class="p">[</span><span class="n">s</span> <span class="k">for</span> <span class="n">s</span> <span class="ow">in</span> <span class="n">comp</span> <span class="k">if</span> <span class="n">s</span><span class="o">.</span><span class="n">oxi_state</span> <span class="o">*</span> <span class="n">ox</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">],</span>
                    <span class="n">key</span><span class="o">=</span><span class="k">lambda</span> <span class="n">ss</span><span class="p">:</span> <span class="nb">abs</span><span class="p">(</span><span class="n">ss</span><span class="o">.</span><span class="n">oxi_state</span><span class="p">),</span>
                <span class="p">)</span>

                <span class="k">if</span> <span class="n">sp_to_remove</span> <span class="o">==</span> <span class="n">sp</span><span class="p">:</span>
                    <span class="n">common_charge</span> <span class="o">=</span> <span class="n">lcm</span><span class="p">(</span><span class="nb">int</span><span class="p">(</span><span class="nb">abs</span><span class="p">(</span><span class="n">sp</span><span class="o">.</span><span class="n">oxi_state</span><span class="p">)),</span> <span class="nb">int</span><span class="p">(</span><span class="nb">abs</span><span class="p">(</span><span class="n">ox</span><span class="p">)))</span>
                    <span class="n">ndopant</span> <span class="o">=</span> <span class="n">common_charge</span> <span class="o">/</span> <span class="nb">abs</span><span class="p">(</span><span class="n">ox</span><span class="p">)</span>
                    <span class="n">nsp_to_remove</span> <span class="o">=</span> <span class="n">common_charge</span> <span class="o">/</span> <span class="nb">abs</span><span class="p">(</span><span class="n">sp</span><span class="o">.</span><span class="n">oxi_state</span><span class="p">)</span>
                    <span class="n">logger</span><span class="o">.</span><span class="n">info</span><span class="p">(</span>
                        <span class="s2">&quot;Doping </span><span class="si">%d</span><span class="s2"> </span><span class="si">%s</span><span class="s2"> with </span><span class="si">%d</span><span class="s2"> </span><span class="si">%s</span><span class="s2">.&quot;</span>
                        <span class="o">%</span> <span class="p">(</span><span class="n">nsp_to_remove</span><span class="p">,</span> <span class="n">sp</span><span class="p">,</span> <span class="n">ndopant</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">dopant</span><span class="p">)</span>
                    <span class="p">)</span>
                    <span class="n">supercell</span><span class="o">.</span><span class="n">replace_species</span><span class="p">(</span>
                        <span class="p">{</span>
                            <span class="n">sp</span><span class="p">:</span> <span class="p">{</span>
                                <span class="n">sp</span><span class="p">:</span> <span class="p">(</span><span class="n">nsp</span> <span class="o">-</span> <span class="n">nsp_to_remove</span><span class="p">)</span> <span class="o">/</span> <span class="n">nsp</span><span class="p">,</span>
                                <span class="bp">self</span><span class="o">.</span><span class="n">dopant</span><span class="p">:</span> <span class="n">ndopant</span> <span class="o">/</span> <span class="n">nsp</span><span class="p">,</span>
                            <span class="p">}</span>
                        <span class="p">}</span>
                    <span class="p">)</span>
                <span class="k">else</span><span class="p">:</span>
                    <span class="n">ox_diff</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="nb">abs</span><span class="p">(</span><span class="nb">round</span><span class="p">(</span><span class="n">sp</span><span class="o">.</span><span class="n">oxi_state</span> <span class="o">-</span> <span class="n">ox</span><span class="p">)))</span>
                    <span class="n">vac_ox</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="nb">abs</span><span class="p">(</span><span class="n">sp_to_remove</span><span class="o">.</span><span class="n">oxi_state</span><span class="p">))</span>
                    <span class="n">common_charge</span> <span class="o">=</span> <span class="n">lcm</span><span class="p">(</span><span class="n">vac_ox</span><span class="p">,</span> <span class="n">ox_diff</span><span class="p">)</span>
                    <span class="n">ndopant</span> <span class="o">=</span> <span class="n">common_charge</span> <span class="o">/</span> <span class="n">ox_diff</span>
                    <span class="n">nx_to_remove</span> <span class="o">=</span> <span class="n">common_charge</span> <span class="o">/</span> <span class="n">vac_ox</span>
                    <span class="n">nx</span> <span class="o">=</span> <span class="n">supercell</span><span class="o">.</span><span class="n">composition</span><span class="p">[</span><span class="n">sp_to_remove</span><span class="p">]</span>
                    <span class="n">logger</span><span class="o">.</span><span class="n">info</span><span class="p">(</span>
                        <span class="s2">&quot;Doping </span><span class="si">%d</span><span class="s2"> </span><span class="si">%s</span><span class="s2"> with </span><span class="si">%s</span><span class="s2"> and removing </span><span class="si">%d</span><span class="s2"> </span><span class="si">%s</span><span class="s2">.&quot;</span>
                        <span class="o">%</span> <span class="p">(</span><span class="n">ndopant</span><span class="p">,</span> <span class="n">sp</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">dopant</span><span class="p">,</span> <span class="n">nx_to_remove</span><span class="p">,</span> <span class="n">sp_to_remove</span><span class="p">)</span>
                    <span class="p">)</span>
                    <span class="n">supercell</span><span class="o">.</span><span class="n">replace_species</span><span class="p">(</span>
                        <span class="p">{</span>
                            <span class="n">sp</span><span class="p">:</span> <span class="p">{</span><span class="n">sp</span><span class="p">:</span> <span class="p">(</span><span class="n">nsp</span> <span class="o">-</span> <span class="n">ndopant</span><span class="p">)</span> <span class="o">/</span> <span class="n">nsp</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">dopant</span><span class="p">:</span> <span class="n">ndopant</span> <span class="o">/</span> <span class="n">nsp</span><span class="p">},</span>
                            <span class="n">sp_to_remove</span><span class="p">:</span> <span class="p">{</span><span class="n">sp_to_remove</span><span class="p">:</span> <span class="p">(</span><span class="n">nx</span> <span class="o">-</span> <span class="n">nx_to_remove</span><span class="p">)</span> <span class="o">/</span> <span class="n">nx</span><span class="p">},</span>
                        <span class="p">}</span>
                    <span class="p">)</span>
            <span class="k">elif</span> <span class="nb">abs</span><span class="p">(</span><span class="n">sp</span><span class="o">.</span><span class="n">oxi_state</span><span class="p">)</span> <span class="o">&gt;</span> <span class="nb">abs</span><span class="p">(</span><span class="n">ox</span><span class="p">):</span>
                <span class="c1"># Strategy: replace the target species with dopant and also</span>
                <span class="c1"># remove some opposite charged species for charge neutrality</span>
                <span class="k">if</span> <span class="n">ox</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">:</span>
                    <span class="n">sp_to_remove</span> <span class="o">=</span> <span class="nb">max</span><span class="p">(</span>
                        <span class="n">supercell</span><span class="o">.</span><span class="n">composition</span><span class="o">.</span><span class="n">keys</span><span class="p">(),</span> <span class="n">key</span><span class="o">=</span><span class="k">lambda</span> <span class="n">el</span><span class="p">:</span> <span class="n">el</span><span class="o">.</span><span class="n">X</span>
                    <span class="p">)</span>
                <span class="k">else</span><span class="p">:</span>
                    <span class="n">sp_to_remove</span> <span class="o">=</span> <span class="nb">min</span><span class="p">(</span>
                        <span class="n">supercell</span><span class="o">.</span><span class="n">composition</span><span class="o">.</span><span class="n">keys</span><span class="p">(),</span> <span class="n">key</span><span class="o">=</span><span class="k">lambda</span> <span class="n">el</span><span class="p">:</span> <span class="n">el</span><span class="o">.</span><span class="n">X</span>
                    <span class="p">)</span>
                <span class="c1"># Confirm species are of opposite oxidation states.</span>
                <span class="k">assert</span> <span class="n">sp_to_remove</span><span class="o">.</span><span class="n">oxi_state</span> <span class="o">*</span> <span class="n">sp</span><span class="o">.</span><span class="n">oxi_state</span> <span class="o">&lt;</span> <span class="mi">0</span>

                <span class="n">ox_diff</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="nb">abs</span><span class="p">(</span><span class="nb">round</span><span class="p">(</span><span class="n">sp</span><span class="o">.</span><span class="n">oxi_state</span> <span class="o">-</span> <span class="n">ox</span><span class="p">)))</span>
                <span class="n">anion_ox</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="nb">abs</span><span class="p">(</span><span class="n">sp_to_remove</span><span class="o">.</span><span class="n">oxi_state</span><span class="p">))</span>
                <span class="n">nx</span> <span class="o">=</span> <span class="n">supercell</span><span class="o">.</span><span class="n">composition</span><span class="p">[</span><span class="n">sp_to_remove</span><span class="p">]</span>
                <span class="n">common_charge</span> <span class="o">=</span> <span class="n">lcm</span><span class="p">(</span><span class="n">anion_ox</span><span class="p">,</span> <span class="n">ox_diff</span><span class="p">)</span>
                <span class="n">ndopant</span> <span class="o">=</span> <span class="n">common_charge</span> <span class="o">/</span> <span class="n">ox_diff</span>
                <span class="n">nx_to_remove</span> <span class="o">=</span> <span class="n">common_charge</span> <span class="o">/</span> <span class="n">anion_ox</span>
                <span class="n">logger</span><span class="o">.</span><span class="n">info</span><span class="p">(</span>
                    <span class="s2">&quot;Doping </span><span class="si">%d</span><span class="s2"> </span><span class="si">%s</span><span class="s2"> with </span><span class="si">%s</span><span class="s2"> and removing </span><span class="si">%d</span><span class="s2"> </span><span class="si">%s</span><span class="s2">.&quot;</span>
                    <span class="o">%</span> <span class="p">(</span><span class="n">ndopant</span><span class="p">,</span> <span class="n">sp</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">dopant</span><span class="p">,</span> <span class="n">nx_to_remove</span><span class="p">,</span> <span class="n">sp_to_remove</span><span class="p">)</span>
                <span class="p">)</span>
                <span class="n">supercell</span><span class="o">.</span><span class="n">replace_species</span><span class="p">(</span>
                    <span class="p">{</span>
                        <span class="n">sp</span><span class="p">:</span> <span class="p">{</span><span class="n">sp</span><span class="p">:</span> <span class="p">(</span><span class="n">nsp</span> <span class="o">-</span> <span class="n">ndopant</span><span class="p">)</span> <span class="o">/</span> <span class="n">nsp</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">dopant</span><span class="p">:</span> <span class="n">ndopant</span> <span class="o">/</span> <span class="n">nsp</span><span class="p">},</span>
                        <span class="n">sp_to_remove</span><span class="p">:</span> <span class="p">{</span><span class="n">sp_to_remove</span><span class="p">:</span> <span class="p">(</span><span class="n">nx</span> <span class="o">-</span> <span class="n">nx_to_remove</span><span class="p">)</span> <span class="o">/</span> <span class="n">nx</span><span class="p">},</span>
                    <span class="p">}</span>
                <span class="p">)</span>

            <span class="n">ss</span> <span class="o">=</span> <span class="n">t</span><span class="o">.</span><span class="n">apply_transformation</span><span class="p">(</span>
                <span class="n">supercell</span><span class="p">,</span> <span class="n">return_ranked_list</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">max_structures_per_enum</span>
            <span class="p">)</span>
            <span class="n">logger</span><span class="o">.</span><span class="n">info</span><span class="p">(</span><span class="s2">&quot;</span><span class="si">%s</span><span class="s2"> distinct structures&quot;</span> <span class="o">%</span> <span class="nb">len</span><span class="p">(</span><span class="n">ss</span><span class="p">))</span>
            <span class="n">all_structures</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">ss</span><span class="p">)</span>

        <span class="n">logger</span><span class="o">.</span><span class="n">info</span><span class="p">(</span><span class="s2">&quot;Total </span><span class="si">%s</span><span class="s2"> doped structures&quot;</span> <span class="o">%</span> <span class="nb">len</span><span class="p">(</span><span class="n">all_structures</span><span class="p">))</span>
        <span class="k">if</span> <span class="n">return_ranked_list</span><span class="p">:</span>
            <span class="k">return</span> <span class="n">all_structures</span><span class="p">[:</span><span class="n">return_ranked_list</span><span class="p">]</span>

        <span class="k">return</span> <span class="n">all_structures</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="s2">&quot;structure&quot;</span><span class="p">]</span></div>

    <span class="nd">@property</span>
    <span class="k">def</span> <span class="nf">inverse</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;Returns: None&quot;&quot;&quot;</span>
        <span class="k">return</span> <span class="kc">None</span>

    <span class="nd">@property</span>
    <span class="k">def</span> <span class="nf">is_one_to_many</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;Returns: True&quot;&quot;&quot;</span>
        <span class="k">return</span> <span class="kc">True</span></div>


<div class="viewcode-block" id="SlabTransformation"><a class="viewcode-back" href="../../../pymatgen.transformations.advanced_transformations.html#pymatgen.transformations.advanced_transformations.SlabTransformation">[docs]</a><span class="k">class</span> <span class="nc">SlabTransformation</span><span class="p">(</span><span class="n">AbstractTransformation</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    A transformation that creates a slab from a structure.</span>
<span class="sd">    &quot;&quot;&quot;</span>

    <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span>
        <span class="bp">self</span><span class="p">,</span>
        <span class="n">miller_index</span><span class="p">,</span>
        <span class="n">min_slab_size</span><span class="p">,</span>
        <span class="n">min_vacuum_size</span><span class="p">,</span>
        <span class="n">lll_reduce</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span>
        <span class="n">center_slab</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span>
        <span class="n">in_unit_planes</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span>
        <span class="n">primitive</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span>
        <span class="n">max_normal_search</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
        <span class="n">shift</span><span class="o">=</span><span class="mi">0</span><span class="p">,</span>
        <span class="n">tol</span><span class="o">=</span><span class="mf">0.1</span><span class="p">,</span>
    <span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Args:</span>
<span class="sd">            miller_index (3-tuple or list): miller index of slab</span>
<span class="sd">            min_slab_size (float): minimum slab size in angstroms</span>
<span class="sd">            min_vacuum_size (float): minimum size of vacuum</span>
<span class="sd">            lll_reduce (bool): whether to apply LLL reduction</span>
<span class="sd">            center_slab (bool): whether to center the slab</span>
<span class="sd">            primitive (bool): whether to reduce slabs to most primitive cell</span>
<span class="sd">            max_normal_search (int): maximum index to include in linear</span>
<span class="sd">                combinations of indices to find c lattice vector orthogonal</span>
<span class="sd">                to slab surface</span>
<span class="sd">            shift (float): shift to get termination</span>
<span class="sd">            tol (float): tolerance for primitive cell finding</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">miller_index</span> <span class="o">=</span> <span class="n">miller_index</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">min_slab_size</span> <span class="o">=</span> <span class="n">min_slab_size</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">min_vacuum_size</span> <span class="o">=</span> <span class="n">min_vacuum_size</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">lll_reduce</span> <span class="o">=</span> <span class="n">lll_reduce</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">center_slab</span> <span class="o">=</span> <span class="n">center_slab</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">in_unit_planes</span> <span class="o">=</span> <span class="n">in_unit_planes</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">primitive</span> <span class="o">=</span> <span class="n">primitive</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">max_normal_search</span> <span class="o">=</span> <span class="n">max_normal_search</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">shift</span> <span class="o">=</span> <span class="n">shift</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">tol</span> <span class="o">=</span> <span class="n">tol</span>

<div class="viewcode-block" id="SlabTransformation.apply_transformation"><a class="viewcode-back" href="../../../pymatgen.transformations.advanced_transformations.html#pymatgen.transformations.advanced_transformations.SlabTransformation.apply_transformation">[docs]</a>    <span class="k">def</span> <span class="nf">apply_transformation</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">structure</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Applies the transformation.</span>

<span class="sd">        Args:</span>
<span class="sd">            structure: Input Structure</span>

<span class="sd">        Returns:</span>
<span class="sd">            Slab Structures.</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="n">sg</span> <span class="o">=</span> <span class="n">SlabGenerator</span><span class="p">(</span>
            <span class="n">structure</span><span class="p">,</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">miller_index</span><span class="p">,</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">min_slab_size</span><span class="p">,</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">min_vacuum_size</span><span class="p">,</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">lll_reduce</span><span class="p">,</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">center_slab</span><span class="p">,</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">in_unit_planes</span><span class="p">,</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">primitive</span><span class="p">,</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">max_normal_search</span><span class="p">,</span>
        <span class="p">)</span>
        <span class="n">slab</span> <span class="o">=</span> <span class="n">sg</span><span class="o">.</span><span class="n">get_slab</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">shift</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">tol</span><span class="p">)</span>
        <span class="k">return</span> <span class="n">slab</span></div>

    <span class="nd">@property</span>
    <span class="k">def</span> <span class="nf">inverse</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;Returns: None&quot;&quot;&quot;</span>
        <span class="k">return</span> <span class="kc">None</span>

    <span class="nd">@property</span>
    <span class="k">def</span> <span class="nf">is_one_to_many</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;Returns: False&quot;&quot;&quot;</span>
        <span class="k">return</span> <span class="kc">False</span></div>


<div class="viewcode-block" id="DisorderOrderedTransformation"><a class="viewcode-back" href="../../../pymatgen.transformations.advanced_transformations.html#pymatgen.transformations.advanced_transformations.DisorderOrderedTransformation">[docs]</a><span class="k">class</span> <span class="nc">DisorderOrderedTransformation</span><span class="p">(</span><span class="n">AbstractTransformation</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    Not to be confused with OrderDisorderedTransformation,</span>
<span class="sd">    this transformation attempts to obtain a</span>
<span class="sd">    *disordered* structure from an input ordered structure.</span>
<span class="sd">    This may or may not be physically plausible, further</span>
<span class="sd">    inspection of the returned structures is advised.</span>
<span class="sd">    The main purpose for this transformation is for structure</span>
<span class="sd">    matching to crystal prototypes for structures that have</span>
<span class="sd">    been derived from a parent prototype structure by</span>
<span class="sd">    substitutions or alloying additions.</span>
<span class="sd">    &quot;&quot;&quot;</span>

    <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">max_sites_to_merge</span><span class="o">=</span><span class="mi">2</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Args:</span>
<span class="sd">            max_sites_to_merge: only merge this number of sites together</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">max_sites_to_merge</span> <span class="o">=</span> <span class="n">max_sites_to_merge</span>

<div class="viewcode-block" id="DisorderOrderedTransformation.apply_transformation"><a class="viewcode-back" href="../../../pymatgen.transformations.advanced_transformations.html#pymatgen.transformations.advanced_transformations.DisorderOrderedTransformation.apply_transformation">[docs]</a>    <span class="k">def</span> <span class="nf">apply_transformation</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">structure</span><span class="p">,</span> <span class="n">return_ranked_list</span><span class="o">=</span><span class="kc">False</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Args:</span>
<span class="sd">            structure: ordered structure</span>
<span class="sd">            return_ranked_list: as in other pymatgen Transformations</span>

<span class="sd">        Returns:</span>
<span class="sd">            Transformed disordered structure(s)</span>
<span class="sd">        &quot;&quot;&quot;</span>

        <span class="k">if</span> <span class="ow">not</span> <span class="n">structure</span><span class="o">.</span><span class="n">is_ordered</span><span class="p">:</span>
            <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s2">&quot;This transformation is for disordered structures only.&quot;</span><span class="p">)</span>

        <span class="n">partitions</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_partition_species</span><span class="p">(</span>
            <span class="n">structure</span><span class="o">.</span><span class="n">composition</span><span class="p">,</span> <span class="n">max_components</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">max_sites_to_merge</span>
        <span class="p">)</span>
        <span class="n">disorder_mappings</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_get_disorder_mappings</span><span class="p">(</span>
            <span class="n">structure</span><span class="o">.</span><span class="n">composition</span><span class="p">,</span> <span class="n">partitions</span>
        <span class="p">)</span>

        <span class="n">disordered_structures</span> <span class="o">=</span> <span class="p">[]</span>
        <span class="k">for</span> <span class="n">mapping</span> <span class="ow">in</span> <span class="n">disorder_mappings</span><span class="p">:</span>
            <span class="n">disordered_structure</span> <span class="o">=</span> <span class="n">structure</span><span class="o">.</span><span class="n">copy</span><span class="p">()</span>
            <span class="n">disordered_structure</span><span class="o">.</span><span class="n">replace_species</span><span class="p">(</span><span class="n">mapping</span><span class="p">)</span>
            <span class="n">disordered_structures</span><span class="o">.</span><span class="n">append</span><span class="p">(</span>
                <span class="p">{</span><span class="s2">&quot;structure&quot;</span><span class="p">:</span> <span class="n">disordered_structure</span><span class="p">,</span> <span class="s2">&quot;mapping&quot;</span><span class="p">:</span> <span class="n">mapping</span><span class="p">}</span>
            <span class="p">)</span>

        <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">disordered_structures</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
            <span class="k">return</span> <span class="kc">None</span>
        <span class="k">elif</span> <span class="ow">not</span> <span class="n">return_ranked_list</span><span class="p">:</span>
            <span class="k">return</span> <span class="n">disordered_structures</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="s2">&quot;structure&quot;</span><span class="p">]</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">disordered_structures</span><span class="p">)</span> <span class="o">&gt;</span> <span class="n">return_ranked_list</span><span class="p">:</span>
                <span class="n">disordered_structures</span> <span class="o">=</span> <span class="n">disordered_structures</span><span class="p">[</span><span class="mi">0</span><span class="p">:</span><span class="n">return_ranked_list</span><span class="p">]</span>
            <span class="k">return</span> <span class="n">disordered_structures</span></div>

    <span class="nd">@property</span>
    <span class="k">def</span> <span class="nf">inverse</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;Returns: None&quot;&quot;&quot;</span>
        <span class="k">return</span> <span class="kc">None</span>

    <span class="nd">@property</span>
    <span class="k">def</span> <span class="nf">is_one_to_many</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;Returns: True&quot;&quot;&quot;</span>
        <span class="k">return</span> <span class="kc">True</span>

    <span class="nd">@staticmethod</span>
    <span class="k">def</span> <span class="nf">_partition_species</span><span class="p">(</span><span class="n">composition</span><span class="p">,</span> <span class="n">max_components</span><span class="o">=</span><span class="mi">2</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Private method to split a list of species into</span>
<span class="sd">        various partitions.</span>
<span class="sd">        &quot;&quot;&quot;</span>

        <span class="k">def</span> <span class="nf">_partition</span><span class="p">(</span><span class="n">collection</span><span class="p">):</span>
            <span class="c1"># thanks https://stackoverflow.com/a/30134039</span>

            <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">collection</span><span class="p">)</span> <span class="o">==</span> <span class="mi">1</span><span class="p">:</span>
                <span class="k">yield</span> <span class="p">[</span><span class="n">collection</span><span class="p">]</span>
                <span class="k">return</span>

            <span class="n">first</span> <span class="o">=</span> <span class="n">collection</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
            <span class="k">for</span> <span class="n">smaller</span> <span class="ow">in</span> <span class="n">_partition</span><span class="p">(</span><span class="n">collection</span><span class="p">[</span><span class="mi">1</span><span class="p">:]):</span>
                <span class="c1"># insert `first` in each of the subpartition&#39;s subsets</span>
                <span class="k">for</span> <span class="n">n</span><span class="p">,</span> <span class="n">subset</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="n">smaller</span><span class="p">):</span>
                    <span class="k">yield</span> <span class="n">smaller</span><span class="p">[:</span><span class="n">n</span><span class="p">]</span> <span class="o">+</span> <span class="p">[[</span><span class="n">first</span><span class="p">]</span> <span class="o">+</span> <span class="n">subset</span><span class="p">]</span> <span class="o">+</span> <span class="n">smaller</span><span class="p">[</span><span class="n">n</span> <span class="o">+</span> <span class="mi">1</span><span class="p">:]</span>
                <span class="c1"># put `first` in its own subset</span>
                <span class="k">yield</span> <span class="p">[[</span><span class="n">first</span><span class="p">]]</span> <span class="o">+</span> <span class="n">smaller</span>

        <span class="k">def</span> <span class="nf">_sort_partitions</span><span class="p">(</span><span class="n">partitions_to_sort</span><span class="p">):</span>
            <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">            Sort partitions by those we want to check first</span>
<span class="sd">            (typically, merging two sites into one is the</span>
<span class="sd">            one to try first).</span>
<span class="sd">            &quot;&quot;&quot;</span>

            <span class="n">partition_indices</span> <span class="o">=</span> <span class="p">[</span>
                <span class="p">(</span><span class="n">idx</span><span class="p">,</span> <span class="p">[</span><span class="nb">len</span><span class="p">(</span><span class="n">p</span><span class="p">)</span> <span class="k">for</span> <span class="n">p</span> <span class="ow">in</span> <span class="n">partition</span><span class="p">])</span>
                <span class="k">for</span> <span class="n">idx</span><span class="p">,</span> <span class="n">partition</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="n">partitions_to_sort</span><span class="p">)</span>
            <span class="p">]</span>

            <span class="c1"># sort by maximum length of partition first (try smallest maximums first)</span>
            <span class="c1"># and secondarily by number of partitions (most partitions first, i.e.</span>
            <span class="c1"># create the &#39;least disordered&#39; structures first)</span>
            <span class="n">partition_indices</span> <span class="o">=</span> <span class="nb">sorted</span><span class="p">(</span>
                <span class="n">partition_indices</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="k">lambda</span> <span class="n">x</span><span class="p">:</span> <span class="p">(</span><span class="nb">max</span><span class="p">(</span><span class="n">x</span><span class="p">[</span><span class="mi">1</span><span class="p">]),</span> <span class="o">-</span><span class="nb">len</span><span class="p">(</span><span class="n">x</span><span class="p">[</span><span class="mi">1</span><span class="p">]))</span>
            <span class="p">)</span>

            <span class="c1"># merge at most max_component sites,</span>
            <span class="c1"># e.g. merge at most 2 species into 1 disordered site</span>
            <span class="n">partition_indices</span> <span class="o">=</span> <span class="p">[</span>
                <span class="n">x</span> <span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="n">partition_indices</span> <span class="k">if</span> <span class="nb">max</span><span class="p">(</span><span class="n">x</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span> <span class="o">&lt;=</span> <span class="n">max_components</span>
            <span class="p">]</span>

            <span class="n">partition_indices</span><span class="o">.</span><span class="n">pop</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>  <span class="c1"># this is just the input structure</span>

            <span class="n">sorted_partitions</span> <span class="o">=</span> <span class="p">[</span><span class="n">partitions_to_sort</span><span class="p">[</span><span class="n">x</span><span class="p">[</span><span class="mi">0</span><span class="p">]]</span> <span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="n">partition_indices</span><span class="p">]</span>

            <span class="k">return</span> <span class="n">sorted_partitions</span>

        <span class="n">collection</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="n">composition</span><span class="o">.</span><span class="n">keys</span><span class="p">())</span>
        <span class="n">partitions</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="n">_partition</span><span class="p">(</span><span class="n">collection</span><span class="p">))</span>
        <span class="n">partitions</span> <span class="o">=</span> <span class="n">_sort_partitions</span><span class="p">(</span><span class="n">partitions</span><span class="p">)</span>

        <span class="k">return</span> <span class="n">partitions</span>

    <span class="nd">@staticmethod</span>
    <span class="k">def</span> <span class="nf">_get_disorder_mappings</span><span class="p">(</span><span class="n">composition</span><span class="p">,</span> <span class="n">partitions</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Private method to obtain the mapping to create</span>
<span class="sd">        a disordered structure from a given partition.</span>
<span class="sd">        &quot;&quot;&quot;</span>

        <span class="k">def</span> <span class="nf">_get_replacement_dict_from_partition</span><span class="p">(</span><span class="n">partition</span><span class="p">):</span>
            <span class="n">d</span> <span class="o">=</span> <span class="p">{}</span>  <span class="c1"># to be passed to Structure.replace_species()</span>
            <span class="k">for</span> <span class="n">sp_list</span> <span class="ow">in</span> <span class="n">partition</span><span class="p">:</span>
                <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">sp_list</span><span class="p">)</span> <span class="o">&gt;</span> <span class="mi">1</span><span class="p">:</span>
                    <span class="n">total_occ</span> <span class="o">=</span> <span class="nb">sum</span><span class="p">([</span><span class="n">composition</span><span class="p">[</span><span class="n">sp</span><span class="p">]</span> <span class="k">for</span> <span class="n">sp</span> <span class="ow">in</span> <span class="n">sp_list</span><span class="p">])</span>
                    <span class="n">merged_comp</span> <span class="o">=</span> <span class="p">{</span><span class="n">sp</span><span class="p">:</span> <span class="n">composition</span><span class="p">[</span><span class="n">sp</span><span class="p">]</span> <span class="o">/</span> <span class="n">total_occ</span> <span class="k">for</span> <span class="n">sp</span> <span class="ow">in</span> <span class="n">sp_list</span><span class="p">}</span>
                    <span class="k">for</span> <span class="n">sp</span> <span class="ow">in</span> <span class="n">sp_list</span><span class="p">:</span>
                        <span class="n">d</span><span class="p">[</span><span class="n">sp</span><span class="p">]</span> <span class="o">=</span> <span class="n">merged_comp</span>
            <span class="k">return</span> <span class="n">d</span>

        <span class="n">disorder_mapping</span> <span class="o">=</span> <span class="p">[</span><span class="n">_get_replacement_dict_from_partition</span><span class="p">(</span><span class="n">p</span><span class="p">)</span> <span class="k">for</span> <span class="n">p</span> <span class="ow">in</span> <span class="n">partitions</span><span class="p">]</span>

        <span class="k">return</span> <span class="n">disorder_mapping</span></div>


<div class="viewcode-block" id="GrainBoundaryTransformation"><a class="viewcode-back" href="../../../pymatgen.transformations.advanced_transformations.html#pymatgen.transformations.advanced_transformations.GrainBoundaryTransformation">[docs]</a><span class="k">class</span> <span class="nc">GrainBoundaryTransformation</span><span class="p">(</span><span class="n">AbstractTransformation</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    A transformation that creates a gb from a bulk structure.</span>
<span class="sd">    &quot;&quot;&quot;</span>

    <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span>
        <span class="bp">self</span><span class="p">,</span>
        <span class="n">rotation_axis</span><span class="p">,</span>
        <span class="n">rotation_angle</span><span class="p">,</span>
        <span class="n">expand_times</span><span class="o">=</span><span class="mi">4</span><span class="p">,</span>
        <span class="n">vacuum_thickness</span><span class="o">=</span><span class="mf">0.0</span><span class="p">,</span>
        <span class="n">ab_shift</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
        <span class="n">normal</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span>
        <span class="n">ratio</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span>
        <span class="n">plane</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
        <span class="n">max_search</span><span class="o">=</span><span class="mi">20</span><span class="p">,</span>
        <span class="n">tol_coi</span><span class="o">=</span><span class="mf">1.0e-8</span><span class="p">,</span>
        <span class="n">rm_ratio</span><span class="o">=</span><span class="mf">0.7</span><span class="p">,</span>
        <span class="n">quick_gen</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span>
    <span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Args:</span>
<span class="sd">            rotation_axis (list): Rotation axis of GB in the form of a list of integer</span>
<span class="sd">                e.g.: [1, 1, 0]</span>
<span class="sd">            rotation_angle (float, in unit of degree): rotation angle used to generate GB.</span>
<span class="sd">                Make sure the angle is accurate enough. You can use the enum* functions</span>
<span class="sd">                in this class to extract the accurate angle.</span>
<span class="sd">                e.g.: The rotation angle of sigma 3 twist GB with the rotation axis</span>
<span class="sd">                [1, 1, 1] and GB plane (1, 1, 1) can be 60.000000000 degree.</span>
<span class="sd">                If you do not know the rotation angle, but know the sigma value, we have</span>
<span class="sd">                provide the function get_rotation_angle_from_sigma which is able to return</span>
<span class="sd">                all the rotation angles of sigma value you provided.</span>
<span class="sd">            expand_times (int): The multiple times used to expand one unit grain to larger grain.</span>
<span class="sd">                This is used to tune the grain length of GB to warrant that the two GBs in one</span>
<span class="sd">                cell do not interact with each other. Default set to 4.</span>
<span class="sd">            vacuum_thickness (float): The thickness of vacuum that you want to insert between</span>
<span class="sd">                two grains of the GB. Default to 0.</span>
<span class="sd">            ab_shift (list of float, in unit of a, b vectors of Gb): in plane shift of two grains</span>
<span class="sd">            normal (logic):</span>
<span class="sd">                determine if need to require the c axis of top grain (first transformation matrix)</span>
<span class="sd">                perperdicular to the surface or not.</span>
<span class="sd">                default to false.</span>
<span class="sd">            ratio (list of integers): lattice axial ratio.</span>
<span class="sd">                If True, will try to determine automatically from structure.</span>
<span class="sd">                For cubic system, ratio is not needed and can be set to None.</span>
<span class="sd">                For tetragonal system, ratio = [mu, mv], list of two integers,</span>
<span class="sd">                that is, mu/mv = c2/a2. If it is irrational, set it to None.</span>
<span class="sd">                For orthorhombic system, ratio = [mu, lam, mv], list of three integers,</span>
<span class="sd">                    that is, mu:lam:mv = c2:b2:a2. If irrational for one axis, set it to None.</span>
<span class="sd">                e.g. mu:lam:mv = c2,None,a2, means b2 is irrational.</span>
<span class="sd">                For rhombohedral system, ratio = [mu, mv], list of two integers,</span>
<span class="sd">                that is, mu/mv is the ratio of (1+2*cos(alpha))/cos(alpha).</span>
<span class="sd">                If irrational, set it to None.</span>
<span class="sd">                For hexagonal system, ratio = [mu, mv], list of two integers,</span>
<span class="sd">                that is, mu/mv = c2/a2. If it is irrational, set it to none.</span>
<span class="sd">            plane (list): Grain boundary plane in the form of a list of integers</span>
<span class="sd">                e.g.: [1, 2, 3]. If none, we set it as twist GB. The plane will be perpendicular</span>
<span class="sd">                to the rotation axis.</span>
<span class="sd">            max_search (int): max search for the GB lattice vectors that give the smallest GB</span>
<span class="sd">                lattice. If normal is true, also max search the GB c vector that perpendicular</span>
<span class="sd">                to the plane. For complex GB, if you want to speed up, you can reduce this value.</span>
<span class="sd">                But too small of this value may lead to error.</span>
<span class="sd">            tol_coi (float): tolerance to find the coincidence sites. When making approximations to</span>
<span class="sd">                the ratio needed to generate the GB, you probably need to increase this tolerance to</span>
<span class="sd">                obtain the correct number of coincidence sites. To check the number of coincidence</span>
<span class="sd">                sites are correct or not, you can compare the generated Gb object&#39;s sigma with enum*</span>
<span class="sd">                sigma values (what user expected by input).</span>
<span class="sd">            rm_ratio (float): the criteria to remove the atoms which are too close with each other.</span>
<span class="sd">                rm_ratio * bond_length of bulk system is the criteria of bond length, below which the atom</span>
<span class="sd">                will be removed. Default to 0.7.</span>
<span class="sd">            quick_gen (bool): whether to quickly generate a supercell, if set to true, no need to</span>
<span class="sd">                find the smallest cell.</span>
<span class="sd">        Returns:</span>
<span class="sd">           Grain boundary structure (gb (Structure) object).</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">rotation_axis</span> <span class="o">=</span> <span class="n">rotation_axis</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">rotation_angle</span> <span class="o">=</span> <span class="n">rotation_angle</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">expand_times</span> <span class="o">=</span> <span class="n">expand_times</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">vacuum_thickness</span> <span class="o">=</span> <span class="n">vacuum_thickness</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">ab_shift</span> <span class="o">=</span> <span class="n">ab_shift</span> <span class="ow">or</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">]</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">normal</span> <span class="o">=</span> <span class="n">normal</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">ratio</span> <span class="o">=</span> <span class="n">ratio</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">plane</span> <span class="o">=</span> <span class="n">plane</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">max_search</span> <span class="o">=</span> <span class="n">max_search</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">tol_coi</span> <span class="o">=</span> <span class="n">tol_coi</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">rm_ratio</span> <span class="o">=</span> <span class="n">rm_ratio</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">quick_gen</span> <span class="o">=</span> <span class="n">quick_gen</span>

<div class="viewcode-block" id="GrainBoundaryTransformation.apply_transformation"><a class="viewcode-back" href="../../../pymatgen.transformations.advanced_transformations.html#pymatgen.transformations.advanced_transformations.GrainBoundaryTransformation.apply_transformation">[docs]</a>    <span class="k">def</span> <span class="nf">apply_transformation</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">structure</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Applies the transformation.</span>

<span class="sd">        Args:</span>
<span class="sd">            structure: Input Structure</span>
<span class="sd">            return_ranked_list: Number of structures to return.</span>

<span class="sd">        Returns:</span>
<span class="sd">            Grain boundary Structures.</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="n">gbg</span> <span class="o">=</span> <span class="n">GrainBoundaryGenerator</span><span class="p">(</span><span class="n">structure</span><span class="p">)</span>
        <span class="n">gb_struct</span> <span class="o">=</span> <span class="n">gbg</span><span class="o">.</span><span class="n">gb_from_parameters</span><span class="p">(</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">rotation_axis</span><span class="p">,</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">rotation_angle</span><span class="p">,</span>
            <span class="n">expand_times</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">expand_times</span><span class="p">,</span>
            <span class="n">vacuum_thickness</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">vacuum_thickness</span><span class="p">,</span>
            <span class="n">ab_shift</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">ab_shift</span><span class="p">,</span>
            <span class="n">normal</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">normal</span><span class="p">,</span>
            <span class="n">ratio</span><span class="o">=</span><span class="n">gbg</span><span class="o">.</span><span class="n">get_ratio</span><span class="p">()</span> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">ratio</span> <span class="ow">is</span> <span class="kc">True</span> <span class="k">else</span> <span class="bp">self</span><span class="o">.</span><span class="n">ratio</span><span class="p">,</span>
            <span class="n">plane</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">plane</span><span class="p">,</span>
            <span class="n">max_search</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">max_search</span><span class="p">,</span>
            <span class="n">tol_coi</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">tol_coi</span><span class="p">,</span>
            <span class="n">rm_ratio</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">rm_ratio</span><span class="p">,</span>
            <span class="n">quick_gen</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">quick_gen</span><span class="p">,</span>
        <span class="p">)</span>
        <span class="k">return</span> <span class="n">gb_struct</span></div>

    <span class="nd">@property</span>
    <span class="k">def</span> <span class="nf">inverse</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;Returns: None&quot;&quot;&quot;</span>
        <span class="k">return</span> <span class="kc">None</span>

    <span class="nd">@property</span>
    <span class="k">def</span> <span class="nf">is_one_to_many</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;Returns: False&quot;&quot;&quot;</span>
        <span class="k">return</span> <span class="kc">False</span></div>


<div class="viewcode-block" id="CubicSupercellTransformation"><a class="viewcode-back" href="../../../pymatgen.transformations.advanced_transformations.html#pymatgen.transformations.advanced_transformations.CubicSupercellTransformation">[docs]</a><span class="k">class</span> <span class="nc">CubicSupercellTransformation</span><span class="p">(</span><span class="n">AbstractTransformation</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    A transformation that aims to generate a nearly cubic supercell structure</span>
<span class="sd">    from a structure.</span>

<span class="sd">    The algorithm solves for a transformation matrix that makes the supercell</span>
<span class="sd">    cubic. The matrix must have integer entries, so entries are rounded (in such</span>
<span class="sd">    a way that forces the matrix to be nonsingular). From the supercell</span>
<span class="sd">    resulting from this transformation matrix, vector projections are used to</span>
<span class="sd">    determine the side length of the largest cube that can fit inside the</span>
<span class="sd">    supercell. The algorithm will iteratively increase the size of the supercell</span>
<span class="sd">    until the largest inscribed cube&#39;s side length is at least &#39;min_length&#39;</span>
<span class="sd">    and the number of atoms in the supercell falls in the range</span>
<span class="sd">    ``min_atoms &lt; n &lt; max_atoms``.</span>
<span class="sd">    &quot;&quot;&quot;</span>

    <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span>
        <span class="bp">self</span><span class="p">,</span>
        <span class="n">min_atoms</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">int</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span><span class="p">,</span>
        <span class="n">max_atoms</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">int</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span><span class="p">,</span>
        <span class="n">min_length</span><span class="p">:</span> <span class="nb">float</span> <span class="o">=</span> <span class="mf">15.0</span><span class="p">,</span>
        <span class="n">force_diagonal</span><span class="p">:</span> <span class="nb">bool</span> <span class="o">=</span> <span class="kc">False</span><span class="p">,</span>
    <span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Args:</span>
<span class="sd">            max_atoms: Maximum number of atoms allowed in the supercell.</span>
<span class="sd">            min_atoms: Minimum number of atoms allowed in the supercell.</span>
<span class="sd">            min_length: Minimum length of the smallest supercell lattice vector.</span>
<span class="sd">            force_diagonal: If True, return a transformation with a diagonal</span>
<span class="sd">                transformation matrix.</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">min_atoms</span> <span class="o">=</span> <span class="n">min_atoms</span> <span class="k">if</span> <span class="n">min_atoms</span> <span class="k">else</span> <span class="o">-</span><span class="n">np</span><span class="o">.</span><span class="n">Inf</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">max_atoms</span> <span class="o">=</span> <span class="n">max_atoms</span> <span class="k">if</span> <span class="n">max_atoms</span> <span class="k">else</span> <span class="n">np</span><span class="o">.</span><span class="n">Inf</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">min_length</span> <span class="o">=</span> <span class="n">min_length</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">force_diagonal</span> <span class="o">=</span> <span class="n">force_diagonal</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">transformation_matrix</span> <span class="o">=</span> <span class="kc">None</span>

<div class="viewcode-block" id="CubicSupercellTransformation.apply_transformation"><a class="viewcode-back" href="../../../pymatgen.transformations.advanced_transformations.html#pymatgen.transformations.advanced_transformations.CubicSupercellTransformation.apply_transformation">[docs]</a>    <span class="k">def</span> <span class="nf">apply_transformation</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">structure</span><span class="p">:</span> <span class="n">Structure</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">Structure</span><span class="p">:</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        The algorithm solves for a transformation matrix that makes the</span>
<span class="sd">        supercell cubic. The matrix must have integer entries, so entries are</span>
<span class="sd">        rounded (in such a way that forces the matrix to be nonsingular). From</span>
<span class="sd">        the supercell resulting from this transformation matrix, vector</span>
<span class="sd">        projections are used to determine the side length of the largest cube</span>
<span class="sd">        that can fit inside the supercell. The algorithm will iteratively</span>
<span class="sd">        increase the size of the supercell until the largest inscribed cube&#39;s</span>
<span class="sd">        side length is at least &#39;num_nn_dists&#39; times the nearest neighbor</span>
<span class="sd">        distance and the number of atoms in the supercell falls in the range</span>
<span class="sd">        defined by min_atoms and max_atoms.</span>

<span class="sd">        Returns:</span>
<span class="sd">            supercell: Transformed supercell.</span>
<span class="sd">        &quot;&quot;&quot;</span>

        <span class="n">lat_vecs</span> <span class="o">=</span> <span class="n">structure</span><span class="o">.</span><span class="n">lattice</span><span class="o">.</span><span class="n">matrix</span>

        <span class="c1"># boolean for if a sufficiently large supercell has been created</span>
        <span class="n">sc_not_found</span> <span class="o">=</span> <span class="kc">True</span>

        <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">force_diagonal</span><span class="p">:</span>
            <span class="n">scale</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">min_length</span> <span class="o">/</span> <span class="n">np</span><span class="o">.</span><span class="n">array</span><span class="p">(</span><span class="n">structure</span><span class="o">.</span><span class="n">lattice</span><span class="o">.</span><span class="n">abc</span><span class="p">)</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">transformation_matrix</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">diag</span><span class="p">(</span><span class="n">np</span><span class="o">.</span><span class="n">ceil</span><span class="p">(</span><span class="n">scale</span><span class="p">)</span><span class="o">.</span><span class="n">astype</span><span class="p">(</span><span class="nb">int</span><span class="p">))</span>
            <span class="n">st</span> <span class="o">=</span> <span class="n">SupercellTransformation</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">transformation_matrix</span><span class="p">)</span>
            <span class="k">return</span> <span class="n">st</span><span class="o">.</span><span class="n">apply_transformation</span><span class="p">(</span><span class="n">structure</span><span class="p">)</span>

        <span class="c1"># target_threshold is used as the desired cubic side lengths</span>
        <span class="n">target_sc_size</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">min_length</span>
        <span class="k">while</span> <span class="n">sc_not_found</span><span class="p">:</span>
            <span class="n">target_sc_lat_vecs</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">eye</span><span class="p">(</span><span class="mi">3</span><span class="p">,</span> <span class="mi">3</span><span class="p">)</span> <span class="o">*</span> <span class="n">target_sc_size</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">transformation_matrix</span> <span class="o">=</span> <span class="n">target_sc_lat_vecs</span> <span class="o">@</span> <span class="n">np</span><span class="o">.</span><span class="n">linalg</span><span class="o">.</span><span class="n">inv</span><span class="p">(</span><span class="n">lat_vecs</span><span class="p">)</span>

            <span class="c1"># round the entries of T and force T to be nonsingular</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">transformation_matrix</span> <span class="o">=</span> <span class="n">_round_and_make_arr_singular</span><span class="p">(</span>
                <span class="bp">self</span><span class="o">.</span><span class="n">transformation_matrix</span>
            <span class="p">)</span>

            <span class="n">proposed_sc_lat_vecs</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">transformation_matrix</span> <span class="o">@</span> <span class="n">lat_vecs</span>

            <span class="c1"># Find the shortest dimension length and direction</span>
            <span class="n">a</span> <span class="o">=</span> <span class="n">proposed_sc_lat_vecs</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
            <span class="n">b</span> <span class="o">=</span> <span class="n">proposed_sc_lat_vecs</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
            <span class="n">c</span> <span class="o">=</span> <span class="n">proposed_sc_lat_vecs</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span>

            <span class="n">length1_vec</span> <span class="o">=</span> <span class="n">c</span> <span class="o">-</span> <span class="n">_proj</span><span class="p">(</span><span class="n">c</span><span class="p">,</span> <span class="n">a</span><span class="p">)</span>  <span class="c1"># a-c plane</span>
            <span class="n">length2_vec</span> <span class="o">=</span> <span class="n">a</span> <span class="o">-</span> <span class="n">_proj</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">c</span><span class="p">)</span>
            <span class="n">length3_vec</span> <span class="o">=</span> <span class="n">b</span> <span class="o">-</span> <span class="n">_proj</span><span class="p">(</span><span class="n">b</span><span class="p">,</span> <span class="n">a</span><span class="p">)</span>  <span class="c1"># b-a plane</span>
            <span class="n">length4_vec</span> <span class="o">=</span> <span class="n">a</span> <span class="o">-</span> <span class="n">_proj</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">)</span>
            <span class="n">length5_vec</span> <span class="o">=</span> <span class="n">b</span> <span class="o">-</span> <span class="n">_proj</span><span class="p">(</span><span class="n">b</span><span class="p">,</span> <span class="n">c</span><span class="p">)</span>  <span class="c1"># b-c plane</span>
            <span class="n">length6_vec</span> <span class="o">=</span> <span class="n">c</span> <span class="o">-</span> <span class="n">_proj</span><span class="p">(</span><span class="n">c</span><span class="p">,</span> <span class="n">b</span><span class="p">)</span>
            <span class="n">length_vecs</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">array</span><span class="p">(</span>
                <span class="p">[</span>
                    <span class="n">length1_vec</span><span class="p">,</span>
                    <span class="n">length2_vec</span><span class="p">,</span>
                    <span class="n">length3_vec</span><span class="p">,</span>
                    <span class="n">length4_vec</span><span class="p">,</span>
                    <span class="n">length5_vec</span><span class="p">,</span>
                    <span class="n">length6_vec</span><span class="p">,</span>
                <span class="p">]</span>
            <span class="p">)</span>

            <span class="c1"># Get number of atoms</span>
            <span class="n">st</span> <span class="o">=</span> <span class="n">SupercellTransformation</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">transformation_matrix</span><span class="p">)</span>
            <span class="n">superstructure</span> <span class="o">=</span> <span class="n">st</span><span class="o">.</span><span class="n">apply_transformation</span><span class="p">(</span><span class="n">structure</span><span class="p">)</span>
            <span class="n">num_at</span> <span class="o">=</span> <span class="n">superstructure</span><span class="o">.</span><span class="n">num_sites</span>

            <span class="c1"># Check if constraints are satisfied</span>
            <span class="k">if</span> <span class="p">(</span>
                <span class="n">np</span><span class="o">.</span><span class="n">min</span><span class="p">(</span><span class="n">np</span><span class="o">.</span><span class="n">linalg</span><span class="o">.</span><span class="n">norm</span><span class="p">(</span><span class="n">length_vecs</span><span class="p">,</span> <span class="n">axis</span><span class="o">=</span><span class="mi">1</span><span class="p">))</span> <span class="o">&gt;=</span> <span class="bp">self</span><span class="o">.</span><span class="n">min_length</span>
                <span class="ow">and</span> <span class="bp">self</span><span class="o">.</span><span class="n">min_atoms</span> <span class="o">&lt;=</span> <span class="n">num_at</span> <span class="o">&lt;=</span> <span class="bp">self</span><span class="o">.</span><span class="n">max_atoms</span>
            <span class="p">):</span>
                <span class="k">return</span> <span class="n">superstructure</span>
            <span class="k">else</span><span class="p">:</span>
                <span class="c1"># Increase threshold until proposed supercell meets requirements</span>
                <span class="n">target_sc_size</span> <span class="o">+=</span> <span class="mf">0.1</span>
                <span class="k">if</span> <span class="n">num_at</span> <span class="o">&gt;</span> <span class="bp">self</span><span class="o">.</span><span class="n">max_atoms</span><span class="p">:</span>
                    <span class="k">raise</span> <span class="ne">AttributeError</span><span class="p">(</span>
                        <span class="s2">&quot;While trying to solve for the supercell, the max &quot;</span>
                        <span class="s2">&quot;number of atoms was exceeded. Try lowering the number&quot;</span>
                        <span class="s2">&quot;of nearest neighbor distances.&quot;</span>
                    <span class="p">)</span>
        <span class="k">raise</span> <span class="ne">AttributeError</span><span class="p">(</span><span class="s2">&quot;Unable to find cubic supercell&quot;</span><span class="p">)</span></div>

    <span class="nd">@property</span>
    <span class="k">def</span> <span class="nf">inverse</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Returns:</span>
<span class="sd">            None</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="k">return</span> <span class="kc">None</span>

    <span class="nd">@property</span>
    <span class="k">def</span> <span class="nf">is_one_to_many</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Returns:</span>
<span class="sd">            False</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="k">return</span> <span class="kc">False</span></div>


<div class="viewcode-block" id="AddAdsorbateTransformation"><a class="viewcode-back" href="../../../pymatgen.transformations.advanced_transformations.html#pymatgen.transformations.advanced_transformations.AddAdsorbateTransformation">[docs]</a><span class="k">class</span> <span class="nc">AddAdsorbateTransformation</span><span class="p">(</span><span class="n">AbstractTransformation</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    Create absorbate structures.</span>
<span class="sd">    &quot;&quot;&quot;</span>

    <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span>
        <span class="bp">self</span><span class="p">,</span>
        <span class="n">adsorbate</span><span class="p">,</span>
        <span class="n">selective_dynamics</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span>
        <span class="n">height</span><span class="o">=</span><span class="mf">0.9</span><span class="p">,</span>
        <span class="n">mi_vec</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
        <span class="n">repeat</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
        <span class="n">min_lw</span><span class="o">=</span><span class="mf">5.0</span><span class="p">,</span>
        <span class="n">translate</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span>
        <span class="n">reorient</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span>
        <span class="n">find_args</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
    <span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Use AdsorbateSiteFinder to add an absorbate to a slab.</span>

<span class="sd">        Args:</span>
<span class="sd">            adsorbate (Molecule): molecule to add as adsorbate</span>
<span class="sd">            selective_dynamics (bool): flag for whether to assign</span>
<span class="sd">                non-surface sites as fixed for selective dynamics</span>
<span class="sd">            height (float): height criteria for selection of surface sites</span>
<span class="sd">            mi_vec : vector corresponding to the vector</span>
<span class="sd">                concurrent with the miller index, this enables use with</span>
<span class="sd">                slabs that have been reoriented, but the miller vector</span>
<span class="sd">                must be supplied manually</span>
<span class="sd">            repeat (3-tuple or list): repeat argument for supercell generation</span>
<span class="sd">            min_lw (float): minimum length and width of the slab, only used</span>
<span class="sd">                if repeat is None</span>
<span class="sd">            translate (bool): flag on whether to translate the molecule so</span>
<span class="sd">                that its CoM is at the origin prior to adding it to the surface</span>
<span class="sd">            reorient (bool): flag on whether or not to reorient adsorbate</span>
<span class="sd">                along the miller index</span>
<span class="sd">            find_args (dict): dictionary of arguments to be passed to the</span>
<span class="sd">                call to self.find_adsorption_sites, e.g. {&quot;distance&quot;:2.0}</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">adsorbate</span> <span class="o">=</span> <span class="n">adsorbate</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">selective_dynamics</span> <span class="o">=</span> <span class="n">selective_dynamics</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">height</span> <span class="o">=</span> <span class="n">height</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">mi_vec</span> <span class="o">=</span> <span class="n">mi_vec</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">repeat</span> <span class="o">=</span> <span class="n">repeat</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">min_lw</span> <span class="o">=</span> <span class="n">min_lw</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">translate</span> <span class="o">=</span> <span class="n">translate</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">reorient</span> <span class="o">=</span> <span class="n">reorient</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">find_args</span> <span class="o">=</span> <span class="n">find_args</span>

<div class="viewcode-block" id="AddAdsorbateTransformation.apply_transformation"><a class="viewcode-back" href="../../../pymatgen.transformations.advanced_transformations.html#pymatgen.transformations.advanced_transformations.AddAdsorbateTransformation.apply_transformation">[docs]</a>    <span class="k">def</span> <span class="nf">apply_transformation</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">structure</span><span class="p">,</span> <span class="n">return_ranked_list</span><span class="o">=</span><span class="kc">False</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>

<span class="sd">        Args:</span>
<span class="sd">            structure: Must be a Slab structure</span>
<span class="sd">            return_ranked_list:  Whether or not multiple structures are</span>
<span class="sd">                returned. If return_ranked_list is a number, up to that number of</span>
<span class="sd">                structures is returned.</span>

<span class="sd">        Returns: Slab with adsorbate</span>

<span class="sd">        &quot;&quot;&quot;</span>

        <span class="n">sitefinder</span> <span class="o">=</span> <span class="n">AdsorbateSiteFinder</span><span class="p">(</span>
            <span class="n">structure</span><span class="p">,</span>
            <span class="n">selective_dynamics</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">selective_dynamics</span><span class="p">,</span>
            <span class="n">height</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">height</span><span class="p">,</span>
            <span class="n">mi_vec</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">mi_vec</span><span class="p">,</span>
        <span class="p">)</span>

        <span class="n">structures</span> <span class="o">=</span> <span class="n">sitefinder</span><span class="o">.</span><span class="n">generate_adsorption_structures</span><span class="p">(</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">adsorbate</span><span class="p">,</span>
            <span class="n">repeat</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">repeat</span><span class="p">,</span>
            <span class="n">min_lw</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">min_lw</span><span class="p">,</span>
            <span class="n">translate</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">translate</span><span class="p">,</span>
            <span class="n">reorient</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">reorient</span><span class="p">,</span>
            <span class="n">find_args</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">find_args</span><span class="p">,</span>
        <span class="p">)</span>

        <span class="k">if</span> <span class="ow">not</span> <span class="n">return_ranked_list</span><span class="p">:</span>
            <span class="k">return</span> <span class="n">structures</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="k">return</span> <span class="p">[</span>
                <span class="p">{</span><span class="s2">&quot;structure&quot;</span><span class="p">:</span> <span class="n">structure</span><span class="p">}</span>
                <span class="k">for</span> <span class="n">structure</span> <span class="ow">in</span> <span class="n">structures</span><span class="p">[:</span><span class="n">return_ranked_list</span><span class="p">]</span>
            <span class="p">]</span></div>

    <span class="nd">@property</span>
    <span class="k">def</span> <span class="nf">inverse</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;Returns: None&quot;&quot;&quot;</span>
        <span class="k">return</span> <span class="kc">None</span>

    <span class="nd">@property</span>
    <span class="k">def</span> <span class="nf">is_one_to_many</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;Returns: True&quot;&quot;&quot;</span>
        <span class="k">return</span> <span class="kc">True</span></div>


<span class="k">def</span> <span class="nf">_round_and_make_arr_singular</span><span class="p">(</span><span class="n">arr</span><span class="p">:</span> <span class="n">np</span><span class="o">.</span><span class="n">ndarray</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">np</span><span class="o">.</span><span class="n">ndarray</span><span class="p">:</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    This function rounds all elements of a matrix to the nearest integer,</span>
<span class="sd">    unless the rounding scheme causes the matrix to be singular, in which</span>
<span class="sd">    case elements of zero rows or columns in the rounded matrix with the</span>
<span class="sd">    largest absolute valued magnitude in the unrounded matrix will be</span>
<span class="sd">    rounded to the next integer away from zero rather than to the</span>
<span class="sd">    nearest integer.</span>

<span class="sd">    The transformation is as follows. First, all entries in &#39;arr&#39; will be</span>
<span class="sd">    rounded to the nearest integer to yield &#39;arr_rounded&#39;. If &#39;arr_rounded&#39;</span>
<span class="sd">    has any zero rows, then one element in each zero row of &#39;arr_rounded&#39;</span>
<span class="sd">    corresponding to the element in &#39;arr&#39; of that row with the largest</span>
<span class="sd">    absolute valued magnitude will be rounded to the next integer away from</span>
<span class="sd">    zero (see the &#39;_round_away_from_zero(x)&#39; function) rather than the</span>
<span class="sd">    nearest integer. This process is then repeated for zero columns. Also</span>
<span class="sd">    note that if &#39;arr&#39; already has zero rows or columns, then this function</span>
<span class="sd">    will not change those rows/columns.</span>

<span class="sd">    Args:</span>
<span class="sd">        arr: Input matrix</span>

<span class="sd">    Returns:</span>
<span class="sd">        Transformed matrix.</span>
<span class="sd">    &quot;&quot;&quot;</span>

    <span class="k">def</span> <span class="nf">round_away_from_zero</span><span class="p">(</span><span class="n">x</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Returns &#39;x&#39; rounded to the next integer away from 0.</span>
<span class="sd">        If &#39;x&#39; is zero, then returns zero.</span>
<span class="sd">        E.g. -1.2 rounds to -2.0. 1.2 rounds to 2.0.</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="n">abs_x</span> <span class="o">=</span> <span class="nb">abs</span><span class="p">(</span><span class="n">x</span><span class="p">)</span>
        <span class="k">return</span> <span class="n">math</span><span class="o">.</span><span class="n">ceil</span><span class="p">(</span><span class="n">abs_x</span><span class="p">)</span> <span class="o">*</span> <span class="p">(</span><span class="n">abs_x</span> <span class="o">/</span> <span class="n">x</span><span class="p">)</span> <span class="k">if</span> <span class="n">x</span> <span class="o">!=</span> <span class="mi">0</span> <span class="k">else</span> <span class="mi">0</span>

    <span class="n">arr_rounded</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">around</span><span class="p">(</span><span class="n">arr</span><span class="p">)</span>

    <span class="c1"># Zero rows in &#39;arr_rounded&#39; make the array singular, so force zero rows to</span>
    <span class="c1"># be nonzero</span>
    <span class="k">if</span> <span class="p">(</span><span class="o">~</span><span class="n">arr_rounded</span><span class="o">.</span><span class="n">any</span><span class="p">(</span><span class="n">axis</span><span class="o">=</span><span class="mi">1</span><span class="p">))</span><span class="o">.</span><span class="n">any</span><span class="p">():</span>
        <span class="c1"># Check for zero rows in T_rounded</span>

        <span class="c1"># indices of zero rows</span>
        <span class="n">zero_row_idxs</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">where</span><span class="p">(</span><span class="o">~</span><span class="n">arr_rounded</span><span class="o">.</span><span class="n">any</span><span class="p">(</span><span class="n">axis</span><span class="o">=</span><span class="mi">1</span><span class="p">))[</span><span class="mi">0</span><span class="p">]</span>

        <span class="k">for</span> <span class="n">zero_row_idx</span> <span class="ow">in</span> <span class="n">zero_row_idxs</span><span class="p">:</span>  <span class="c1"># loop over zero rows</span>
            <span class="n">zero_row</span> <span class="o">=</span> <span class="n">arr</span><span class="p">[</span><span class="n">zero_row_idx</span><span class="p">,</span> <span class="p">:]</span>

            <span class="c1"># Find the element of the zero row with the largest absolute</span>
            <span class="c1"># magnitude in the original (non-rounded) array (i.e. &#39;arr&#39;)</span>
            <span class="n">matches</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">absolute</span><span class="p">(</span><span class="n">zero_row</span><span class="p">)</span> <span class="o">==</span> <span class="n">np</span><span class="o">.</span><span class="n">amax</span><span class="p">(</span><span class="n">np</span><span class="o">.</span><span class="n">absolute</span><span class="p">(</span><span class="n">zero_row</span><span class="p">))</span>
            <span class="n">col_idx_to_fix</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">where</span><span class="p">(</span><span class="n">matches</span><span class="p">)[</span><span class="mi">0</span><span class="p">]</span>

            <span class="c1"># Break ties for the largest absolute magnitude</span>
            <span class="n">r_idx</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">random</span><span class="o">.</span><span class="n">randint</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">col_idx_to_fix</span><span class="p">))</span>
            <span class="n">col_idx_to_fix</span> <span class="o">=</span> <span class="n">col_idx_to_fix</span><span class="p">[</span><span class="n">r_idx</span><span class="p">]</span>

            <span class="c1"># Round the chosen element away from zero</span>
            <span class="n">arr_rounded</span><span class="p">[</span><span class="n">zero_row_idx</span><span class="p">,</span> <span class="n">col_idx_to_fix</span><span class="p">]</span> <span class="o">=</span> <span class="n">round_away_from_zero</span><span class="p">(</span>
                <span class="n">arr</span><span class="p">[</span><span class="n">zero_row_idx</span><span class="p">,</span> <span class="n">col_idx_to_fix</span><span class="p">]</span>
            <span class="p">)</span>

    <span class="c1"># Repeat process for zero columns</span>
    <span class="k">if</span> <span class="p">(</span><span class="o">~</span><span class="n">arr_rounded</span><span class="o">.</span><span class="n">any</span><span class="p">(</span><span class="n">axis</span><span class="o">=</span><span class="mi">0</span><span class="p">))</span><span class="o">.</span><span class="n">any</span><span class="p">():</span>

        <span class="c1"># Check for zero columns in T_rounded</span>
        <span class="n">zero_col_idxs</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">where</span><span class="p">(</span><span class="o">~</span><span class="n">arr_rounded</span><span class="o">.</span><span class="n">any</span><span class="p">(</span><span class="n">axis</span><span class="o">=</span><span class="mi">0</span><span class="p">))[</span><span class="mi">0</span><span class="p">]</span>
        <span class="k">for</span> <span class="n">zero_col_idx</span> <span class="ow">in</span> <span class="n">zero_col_idxs</span><span class="p">:</span>
            <span class="n">zero_col</span> <span class="o">=</span> <span class="n">arr</span><span class="p">[:,</span> <span class="n">zero_col_idx</span><span class="p">]</span>
            <span class="n">matches</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">absolute</span><span class="p">(</span><span class="n">zero_col</span><span class="p">)</span> <span class="o">==</span> <span class="n">np</span><span class="o">.</span><span class="n">amax</span><span class="p">(</span><span class="n">np</span><span class="o">.</span><span class="n">absolute</span><span class="p">(</span><span class="n">zero_col</span><span class="p">))</span>
            <span class="n">row_idx_to_fix</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">where</span><span class="p">(</span><span class="n">matches</span><span class="p">)[</span><span class="mi">0</span><span class="p">]</span>

            <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="n">row_idx_to_fix</span><span class="p">:</span>
                <span class="n">arr_rounded</span><span class="p">[</span><span class="n">i</span><span class="p">,</span> <span class="n">zero_col_idx</span><span class="p">]</span> <span class="o">=</span> <span class="n">round_away_from_zero</span><span class="p">(</span>
                    <span class="n">arr</span><span class="p">[</span><span class="n">i</span><span class="p">,</span> <span class="n">zero_col_idx</span><span class="p">]</span>
                <span class="p">)</span>
    <span class="k">return</span> <span class="n">arr_rounded</span><span class="o">.</span><span class="n">astype</span><span class="p">(</span><span class="nb">int</span><span class="p">)</span>


<div class="viewcode-block" id="SubstituteSurfaceSiteTransformation"><a class="viewcode-back" href="../../../pymatgen.transformations.advanced_transformations.html#pymatgen.transformations.advanced_transformations.SubstituteSurfaceSiteTransformation">[docs]</a><span class="k">class</span> <span class="nc">SubstituteSurfaceSiteTransformation</span><span class="p">(</span><span class="n">AbstractTransformation</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    Use AdsorptionSiteFinder to perform substitution-type doping on the surface</span>
<span class="sd">    and returns all possible configurations where one dopant is substituted</span>
<span class="sd">    per surface. Can substitute one surface or both.</span>
<span class="sd">    &quot;&quot;&quot;</span>

    <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span>
        <span class="bp">self</span><span class="p">,</span>
        <span class="n">atom</span><span class="p">,</span>
        <span class="n">selective_dynamics</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span>
        <span class="n">height</span><span class="o">=</span><span class="mf">0.9</span><span class="p">,</span>
        <span class="n">mi_vec</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
        <span class="n">target_species</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
        <span class="n">sub_both_sides</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span>
        <span class="n">range_tol</span><span class="o">=</span><span class="mf">1e-2</span><span class="p">,</span>
        <span class="n">dist_from_surf</span><span class="o">=</span><span class="mi">0</span><span class="p">,</span>
    <span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Args:</span>
<span class="sd">            atom (str): atom corresponding to substitutional dopant</span>
<span class="sd">            selective_dynamics (bool): flag for whether to assign</span>
<span class="sd">                non-surface sites as fixed for selective dynamics</span>
<span class="sd">            height (float): height criteria for selection of surface sites</span>
<span class="sd">            mi_vec : vector corresponding to the vector</span>
<span class="sd">                concurrent with the miller index, this enables use with</span>
<span class="sd">                slabs that have been reoriented, but the miller vector</span>
<span class="sd">                must be supplied manually</span>
<span class="sd">            target_species:  List of specific species to substitute</span>
<span class="sd">            sub_both_sides (bool): If true, substitute an equivalent</span>
<span class="sd">                site on the other surface</span>
<span class="sd">            range_tol (float): Find viable substitution sites at a specific</span>
<span class="sd">                distance from the surface +- this tolerance</span>
<span class="sd">            dist_from_surf (float): Distance from the surface to find viable</span>
<span class="sd">                substitution sites, defaults to 0 to substitute at the surface</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">atom</span> <span class="o">=</span> <span class="n">atom</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">selective_dynamics</span> <span class="o">=</span> <span class="n">selective_dynamics</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">height</span> <span class="o">=</span> <span class="n">height</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">mi_vec</span> <span class="o">=</span> <span class="n">mi_vec</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">target_species</span> <span class="o">=</span> <span class="n">target_species</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">sub_both_sides</span> <span class="o">=</span> <span class="n">sub_both_sides</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">range_tol</span> <span class="o">=</span> <span class="n">range_tol</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">dist_from_surf</span> <span class="o">=</span> <span class="n">dist_from_surf</span>

<div class="viewcode-block" id="SubstituteSurfaceSiteTransformation.apply_transformation"><a class="viewcode-back" href="../../../pymatgen.transformations.advanced_transformations.html#pymatgen.transformations.advanced_transformations.SubstituteSurfaceSiteTransformation.apply_transformation">[docs]</a>    <span class="k">def</span> <span class="nf">apply_transformation</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">structure</span><span class="p">,</span> <span class="n">return_ranked_list</span><span class="o">=</span><span class="kc">False</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>

<span class="sd">        Args:</span>
<span class="sd">            structure: Must be a Slab structure</span>
<span class="sd">            return_ranked_list:  Whether or not multiple structures are</span>
<span class="sd">                returned. If return_ranked_list is a number, up to that number of</span>
<span class="sd">                structures is returned.</span>

<span class="sd">        Returns: Slab with sites substituted</span>

<span class="sd">        &quot;&quot;&quot;</span>

        <span class="n">sitefinder</span> <span class="o">=</span> <span class="n">AdsorbateSiteFinder</span><span class="p">(</span>
            <span class="n">structure</span><span class="p">,</span>
            <span class="n">selective_dynamics</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">selective_dynamics</span><span class="p">,</span>
            <span class="n">height</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">height</span><span class="p">,</span>
            <span class="n">mi_vec</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">mi_vec</span><span class="p">,</span>
        <span class="p">)</span>

        <span class="n">structures</span> <span class="o">=</span> <span class="n">sitefinder</span><span class="o">.</span><span class="n">generate_substitution_structures</span><span class="p">(</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">atom</span><span class="p">,</span>
            <span class="n">target_species</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">target_species</span><span class="p">,</span>
            <span class="n">sub_both_sides</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">sub_both_sides</span><span class="p">,</span>
            <span class="n">range_tol</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">range_tol</span><span class="p">,</span>
            <span class="n">dist_from_surf</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">dist_from_surf</span><span class="p">,</span>
        <span class="p">)</span>

        <span class="k">if</span> <span class="ow">not</span> <span class="n">return_ranked_list</span><span class="p">:</span>
            <span class="k">return</span> <span class="n">structures</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="k">return</span> <span class="p">[</span>
                <span class="p">{</span><span class="s2">&quot;structure&quot;</span><span class="p">:</span> <span class="n">structure</span><span class="p">}</span>
                <span class="k">for</span> <span class="n">structure</span> <span class="ow">in</span> <span class="n">structures</span><span class="p">[:</span><span class="n">return_ranked_list</span><span class="p">]</span>
            <span class="p">]</span></div>

    <span class="nd">@property</span>
    <span class="k">def</span> <span class="nf">inverse</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;Returns: None&quot;&quot;&quot;</span>
        <span class="k">return</span> <span class="kc">None</span>

    <span class="nd">@property</span>
    <span class="k">def</span> <span class="nf">is_one_to_many</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;Returns: True&quot;&quot;&quot;</span>
        <span class="k">return</span> <span class="kc">True</span></div>


<span class="k">def</span> <span class="nf">_proj</span><span class="p">(</span><span class="n">b</span><span class="p">,</span> <span class="n">a</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    Returns vector projection (np.ndarray) of vector b (np.ndarray)</span>
<span class="sd">    onto vector a (np.ndarray)</span>
<span class="sd">    &quot;&quot;&quot;</span>
    <span class="k">return</span> <span class="p">(</span><span class="n">b</span><span class="o">.</span><span class="n">T</span> <span class="o">@</span> <span class="p">(</span><span class="n">a</span> <span class="o">/</span> <span class="n">np</span><span class="o">.</span><span class="n">linalg</span><span class="o">.</span><span class="n">norm</span><span class="p">(</span><span class="n">a</span><span class="p">)))</span> <span class="o">*</span> <span class="p">(</span><span class="n">a</span> <span class="o">/</span> <span class="n">np</span><span class="o">.</span><span class="n">linalg</span><span class="o">.</span><span class="n">norm</span><span class="p">(</span><span class="n">a</span><span class="p">))</span>


<div class="viewcode-block" id="SQSTransformation"><a class="viewcode-back" href="../../../pymatgen.transformations.advanced_transformations.html#pymatgen.transformations.advanced_transformations.SQSTransformation">[docs]</a><span class="k">class</span> <span class="nc">SQSTransformation</span><span class="p">(</span><span class="n">AbstractTransformation</span><span class="p">):</span>

    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    A transformation that creates a special quasirandom structure (SQS) from a structure with partial occupancies.</span>
<span class="sd">    &quot;&quot;&quot;</span>

    <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span>
        <span class="bp">self</span><span class="p">,</span>
        <span class="n">scaling</span><span class="p">,</span>
        <span class="n">cluster_size_and_shell</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
        <span class="n">search_time</span><span class="o">=</span><span class="mi">60</span><span class="p">,</span>
        <span class="n">directory</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
        <span class="n">instances</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
        <span class="n">temperature</span><span class="o">=</span><span class="mi">1</span><span class="p">,</span>
        <span class="n">wr</span><span class="o">=</span><span class="mi">1</span><span class="p">,</span>
        <span class="n">wn</span><span class="o">=</span><span class="mi">1</span><span class="p">,</span>
        <span class="n">wd</span><span class="o">=</span><span class="mf">0.5</span><span class="p">,</span>
        <span class="n">tol</span><span class="o">=</span><span class="mf">1e-3</span><span class="p">,</span>
        <span class="n">best_only</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span>
        <span class="n">remove_duplicate_structures</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span>
        <span class="n">reduction_algo</span><span class="o">=</span><span class="s2">&quot;LLL&quot;</span><span class="p">,</span>
    <span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Args:</span>
<span class="sd">            structure (Structure): Disordered pymatgen Structure object</span>
<span class="sd">            scaling (int or list): Scaling factor to determine supercell. Two options are possible:</span>
<span class="sd">                    a. (preferred) Scales number of atoms, e.g., for a structure with 8 atoms,</span>
<span class="sd">                       scaling=4 would lead to a 32 atom supercell</span>
<span class="sd">                    b. A sequence of three scaling factors, e.g., [2, 1, 1], which</span>
<span class="sd">                       specifies that the supercell should have dimensions 2a x b x c</span>
<span class="sd">            cluster_size_and_shell (Optional[Dict[int, int]]): Dictionary of cluster interactions with entries in</span>
<span class="sd">                the form number of atoms: nearest neighbor shell</span>
<span class="sd">        Keyword Args:</span>
<span class="sd">            search_time (float): Time spent looking for the ideal SQS in minutes (default: 60)</span>
<span class="sd">            directory (str): Directory to run mcsqs calculation and store files (default: None</span>
<span class="sd">                runs calculations in a temp directory)</span>
<span class="sd">            instances (int): Specifies the number of parallel instances of mcsqs to run</span>
<span class="sd">                (default: number of cpu cores detected by Python)</span>
<span class="sd">            temperature (int or float): Monte Carlo temperature (default: 1), &quot;T&quot; in atat code</span>
<span class="sd">            wr (int or float): Weight assigned to range of perfect correlation match in objective</span>
<span class="sd">                function (default = 1)</span>
<span class="sd">            wn (int or float): Multiplicative decrease in weight per additional point in cluster (default: 1)</span>
<span class="sd">            wd (int or float): Exponent of decay in weight as function of cluster diameter (default: 0)</span>
<span class="sd">            tol (int or float): Tolerance for matching correlations (default: 1e-3)</span>
<span class="sd">            best_only (bool): only return structures with lowest objective function</span>
<span class="sd">            remove_duplicate_structures (bool): only return unique structures</span>
<span class="sd">            reduction_algo (str): The lattice reduction algorithm to use.</span>
<span class="sd">                Currently supported options are &quot;niggli&quot; or &quot;LLL&quot;.</span>
<span class="sd">                &quot;False&quot; does not reduce structure.</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">scaling</span> <span class="o">=</span> <span class="n">scaling</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">search_time</span> <span class="o">=</span> <span class="n">search_time</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">cluster_size_and_shell</span> <span class="o">=</span> <span class="n">cluster_size_and_shell</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">directory</span> <span class="o">=</span> <span class="n">directory</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">instances</span> <span class="o">=</span> <span class="n">instances</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">temperature</span> <span class="o">=</span> <span class="n">temperature</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">wr</span> <span class="o">=</span> <span class="n">wr</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">wn</span> <span class="o">=</span> <span class="n">wn</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">wd</span> <span class="o">=</span> <span class="n">wd</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">tol</span> <span class="o">=</span> <span class="n">tol</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">best_only</span> <span class="o">=</span> <span class="n">best_only</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">remove_duplicate_structures</span> <span class="o">=</span> <span class="n">remove_duplicate_structures</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">reduction_algo</span> <span class="o">=</span> <span class="n">reduction_algo</span>

    <span class="nd">@staticmethod</span>
    <span class="k">def</span> <span class="nf">_get_max_neighbor_distance</span><span class="p">(</span><span class="n">struc</span><span class="p">,</span> <span class="n">shell</span><span class="p">):</span>

        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Calculate maximum nearest neighbor distance</span>
<span class="sd">        Args:</span>
<span class="sd">            struc: pymatgen Structure object</span>
<span class="sd">            shell: nearest neighbor shell, such that shell=1 is the first nearest</span>
<span class="sd">                neighbor, etc.</span>

<span class="sd">        Returns:</span>
<span class="sd">            maximum nearest neighbor distance, in angstroms</span>
<span class="sd">        &quot;&quot;&quot;</span>

        <span class="n">mdnn</span> <span class="o">=</span> <span class="n">MinimumDistanceNN</span><span class="p">()</span>
        <span class="n">distances</span> <span class="o">=</span> <span class="p">[]</span>

        <span class="k">for</span> <span class="n">site_num</span><span class="p">,</span> <span class="n">site</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="n">struc</span><span class="p">):</span>
            <span class="n">shell_info</span> <span class="o">=</span> <span class="n">mdnn</span><span class="o">.</span><span class="n">get_nn_shell_info</span><span class="p">(</span><span class="n">struc</span><span class="p">,</span> <span class="n">site_num</span><span class="p">,</span> <span class="n">shell</span><span class="p">)</span>
            <span class="k">for</span> <span class="n">entry</span> <span class="ow">in</span> <span class="n">shell_info</span><span class="p">:</span>
                <span class="n">image</span> <span class="o">=</span> <span class="n">entry</span><span class="p">[</span><span class="s2">&quot;image&quot;</span><span class="p">]</span>
                <span class="n">distance</span> <span class="o">=</span> <span class="n">site</span><span class="o">.</span><span class="n">distance</span><span class="p">(</span><span class="n">struc</span><span class="p">[</span><span class="n">entry</span><span class="p">[</span><span class="s2">&quot;site_index&quot;</span><span class="p">]],</span> <span class="n">jimage</span><span class="o">=</span><span class="n">image</span><span class="p">)</span>
                <span class="n">distances</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">distance</span><span class="p">)</span>

        <span class="k">return</span> <span class="nb">max</span><span class="p">(</span><span class="n">distances</span><span class="p">)</span>

    <span class="nd">@staticmethod</span>
    <span class="k">def</span> <span class="nf">_get_disordered_substructure</span><span class="p">(</span><span class="n">struc_disordered</span><span class="p">):</span>

        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Converts disordered structure into a substructure consisting of only disordered sites</span>
<span class="sd">        Args:</span>
<span class="sd">            struc_disordered: pymatgen disordered Structure object</span>
<span class="sd">        Returns:</span>
<span class="sd">            pymatgen Structure object representing a substructure of disordered sites</span>
<span class="sd">        &quot;&quot;&quot;</span>

        <span class="n">disordered_substructure</span> <span class="o">=</span> <span class="n">struc_disordered</span><span class="o">.</span><span class="n">copy</span><span class="p">()</span>

        <span class="n">idx_to_remove</span> <span class="o">=</span> <span class="p">[]</span>
        <span class="k">for</span> <span class="n">idx</span><span class="p">,</span> <span class="n">site</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="n">disordered_substructure</span><span class="o">.</span><span class="n">sites</span><span class="p">):</span>
            <span class="k">if</span> <span class="n">site</span><span class="o">.</span><span class="n">is_ordered</span><span class="p">:</span>
                <span class="n">idx_to_remove</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">idx</span><span class="p">)</span>
        <span class="n">disordered_substructure</span><span class="o">.</span><span class="n">remove_sites</span><span class="p">(</span><span class="n">idx_to_remove</span><span class="p">)</span>

        <span class="k">return</span> <span class="n">disordered_substructure</span>

    <span class="nd">@staticmethod</span>
    <span class="k">def</span> <span class="nf">_sqs_cluster_estimate</span><span class="p">(</span>
        <span class="n">struc_disordered</span><span class="p">,</span> <span class="n">cluster_size_and_shell</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="n">Dict</span><span class="p">[</span><span class="nb">int</span><span class="p">,</span> <span class="nb">int</span><span class="p">]]</span> <span class="o">=</span> <span class="kc">None</span>
    <span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Set up an ATAT cluster.out file for a given structure and set of constraints</span>
<span class="sd">        Args:</span>
<span class="sd">            struc_disordered: disordered pymatgen Structure object</span>
<span class="sd">            cluster_size_and_shell: dict of integers {cluster: shell}</span>
<span class="sd">        Returns:</span>
<span class="sd">            dict of {cluster size: distance in angstroms} for mcsqs calculation</span>
<span class="sd">        &quot;&quot;&quot;</span>

        <span class="n">cluster_size_and_shell</span> <span class="o">=</span> <span class="n">cluster_size_and_shell</span> <span class="ow">or</span> <span class="p">{</span><span class="mi">2</span><span class="p">:</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">3</span><span class="p">:</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">4</span><span class="p">:</span> <span class="mi">1</span><span class="p">}</span>

        <span class="n">disordered_substructure</span> <span class="o">=</span> <span class="n">SQSTransformation</span><span class="o">.</span><span class="n">_get_disordered_substructure</span><span class="p">(</span>
            <span class="n">struc_disordered</span>
        <span class="p">)</span>

        <span class="n">clusters</span> <span class="o">=</span> <span class="p">{}</span>
        <span class="k">for</span> <span class="n">cluster_size</span><span class="p">,</span> <span class="n">shell</span> <span class="ow">in</span> <span class="n">cluster_size_and_shell</span><span class="o">.</span><span class="n">items</span><span class="p">():</span>
            <span class="n">max_distance</span> <span class="o">=</span> <span class="n">SQSTransformation</span><span class="o">.</span><span class="n">_get_max_neighbor_distance</span><span class="p">(</span>
                <span class="n">disordered_substructure</span><span class="p">,</span> <span class="n">shell</span>
            <span class="p">)</span>
            <span class="n">clusters</span><span class="p">[</span><span class="n">cluster_size</span><span class="p">]</span> <span class="o">=</span> <span class="n">max_distance</span> <span class="o">+</span> <span class="mf">0.01</span>  <span class="c1"># add small tolerance</span>

        <span class="k">return</span> <span class="n">clusters</span>

<div class="viewcode-block" id="SQSTransformation.apply_transformation"><a class="viewcode-back" href="../../../pymatgen.transformations.advanced_transformations.html#pymatgen.transformations.advanced_transformations.SQSTransformation.apply_transformation">[docs]</a>    <span class="k">def</span> <span class="nf">apply_transformation</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">structure</span><span class="p">,</span> <span class="n">return_ranked_list</span><span class="o">=</span><span class="kc">False</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Applies SQS transformation</span>
<span class="sd">        Args:</span>
<span class="sd">            structure (pymatgen Structure): pymatgen Structure with partial occupancies</span>
<span class="sd">            return_ranked_list (bool): number of structures to return</span>
<span class="sd">        Returns:</span>
<span class="sd">            pymatgen Structure which is an SQS of the input structure</span>
<span class="sd">        &quot;&quot;&quot;</span>

        <span class="k">if</span> <span class="n">return_ranked_list</span> <span class="ow">and</span> <span class="bp">self</span><span class="o">.</span><span class="n">instances</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
            <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s2">&quot;mcsqs has no instances, so cannot return a ranked list&quot;</span><span class="p">)</span>
        <span class="k">if</span> <span class="p">(</span>
            <span class="nb">isinstance</span><span class="p">(</span><span class="n">return_ranked_list</span><span class="p">,</span> <span class="nb">int</span><span class="p">)</span>
            <span class="ow">and</span> <span class="nb">isinstance</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">instances</span><span class="p">,</span> <span class="nb">int</span><span class="p">)</span>
            <span class="ow">and</span> <span class="n">return_ranked_list</span> <span class="o">&gt;</span> <span class="bp">self</span><span class="o">.</span><span class="n">instances</span>
        <span class="p">):</span>
            <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span>
                <span class="s2">&quot;return_ranked_list cannot be less that number of instances&quot;</span>
            <span class="p">)</span>

        <span class="n">clusters</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_sqs_cluster_estimate</span><span class="p">(</span><span class="n">structure</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">cluster_size_and_shell</span><span class="p">)</span>

        <span class="c1"># useful for debugging and understanding</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">_last_used_clusters</span> <span class="o">=</span> <span class="n">clusters</span>

        <span class="n">sqs</span> <span class="o">=</span> <span class="n">run_mcsqs</span><span class="p">(</span>
            <span class="n">structure</span><span class="o">=</span><span class="n">structure</span><span class="p">,</span>
            <span class="n">clusters</span><span class="o">=</span><span class="n">clusters</span><span class="p">,</span>
            <span class="n">scaling</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">scaling</span><span class="p">,</span>
            <span class="n">search_time</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">search_time</span><span class="p">,</span>
            <span class="n">directory</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">directory</span><span class="p">,</span>
            <span class="n">instances</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">instances</span><span class="p">,</span>
            <span class="n">temperature</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">temperature</span><span class="p">,</span>
            <span class="n">wr</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">wr</span><span class="p">,</span>
            <span class="n">wn</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">wn</span><span class="p">,</span>
            <span class="n">wd</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">wd</span><span class="p">,</span>
            <span class="n">tol</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">tol</span><span class="p">,</span>
        <span class="p">)</span>

        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_get_unique_bestsqs_strucs</span><span class="p">(</span>
            <span class="n">sqs</span><span class="p">,</span>
            <span class="n">best_only</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">best_only</span><span class="p">,</span>
            <span class="n">return_ranked_list</span><span class="o">=</span><span class="n">return_ranked_list</span><span class="p">,</span>
            <span class="n">remove_duplicate_structures</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">remove_duplicate_structures</span><span class="p">,</span>
            <span class="n">reduction_algo</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">reduction_algo</span><span class="p">,</span>
        <span class="p">)</span></div>

    <span class="nd">@staticmethod</span>
    <span class="k">def</span> <span class="nf">_get_unique_bestsqs_strucs</span><span class="p">(</span>
        <span class="n">sqs</span><span class="p">,</span> <span class="n">best_only</span><span class="p">,</span> <span class="n">return_ranked_list</span><span class="p">,</span> <span class="n">remove_duplicate_structures</span><span class="p">,</span> <span class="n">reduction_algo</span>
    <span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Gets unique sqs structures with lowest objective function. Requires an mcsqs output that has been run</span>
<span class="sd">            in parallel, otherwise returns Sqs.bestsqs</span>
<span class="sd">        Args:</span>
<span class="sd">            sqs (Sqs): Sqs class object.</span>
<span class="sd">            best_only (bool): only return structures with lowest objective function.</span>
<span class="sd">            return_ranked_list (bool): Number of structures to return.</span>
<span class="sd">            remove_duplicate_structures (bool): only return unique structures.</span>
<span class="sd">            reduction_algo (str): The lattice reduction algorithm to use.</span>
<span class="sd">                Currently supported options are &quot;niggli&quot; or &quot;LLL&quot;.</span>
<span class="sd">                &quot;False&quot; does not reduce structure.</span>
<span class="sd">        Returns:</span>
<span class="sd">            list of dicts of the form {&#39;structure&#39;: Structure, &#39;objective_function&#39;: ...}, unless run in serial</span>
<span class="sd">                (returns a single structure Sqs.bestsqs)</span>
<span class="sd">        &quot;&quot;&quot;</span>

        <span class="k">if</span> <span class="ow">not</span> <span class="n">return_ranked_list</span><span class="p">:</span>

            <span class="c1"># return just the structure</span>
            <span class="k">return</span> <span class="n">sqs</span><span class="o">.</span><span class="n">bestsqs</span>

        <span class="k">else</span><span class="p">:</span>

            <span class="n">strucs</span> <span class="o">=</span> <span class="p">[]</span>
            <span class="k">for</span> <span class="n">d</span> <span class="ow">in</span> <span class="n">sqs</span><span class="o">.</span><span class="n">allsqs</span><span class="p">:</span>
                <span class="c1"># filter for best structures only if enabled, else use full sqs.all_sqs list</span>
                <span class="k">if</span> <span class="p">(</span><span class="ow">not</span> <span class="n">best_only</span><span class="p">)</span> <span class="ow">or</span> <span class="p">(</span>
                    <span class="n">best_only</span> <span class="ow">and</span> <span class="n">d</span><span class="p">[</span><span class="s2">&quot;objective_function&quot;</span><span class="p">]</span> <span class="o">==</span> <span class="n">sqs</span><span class="o">.</span><span class="n">objective_function</span>
                <span class="p">):</span>
                    <span class="n">struc</span> <span class="o">=</span> <span class="n">d</span><span class="p">[</span><span class="s2">&quot;structure&quot;</span><span class="p">]</span>
                    <span class="c1"># add temporary objective_function attribute to access objective_function after grouping</span>
                    <span class="n">struc</span><span class="o">.</span><span class="n">objective_function</span> <span class="o">=</span> <span class="n">d</span><span class="p">[</span><span class="s2">&quot;objective_function&quot;</span><span class="p">]</span>
                    <span class="n">strucs</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">struc</span><span class="p">)</span>

            <span class="k">if</span> <span class="n">remove_duplicate_structures</span><span class="p">:</span>
                <span class="n">matcher</span> <span class="o">=</span> <span class="n">StructureMatcher</span><span class="p">()</span>
                <span class="c1"># sort by unique structures ... can take a while for a long list of strucs</span>
                <span class="n">unique_strucs_grouped</span> <span class="o">=</span> <span class="n">matcher</span><span class="o">.</span><span class="n">group_structures</span><span class="p">(</span><span class="n">strucs</span><span class="p">)</span>
                <span class="c1"># get unique structures only</span>
                <span class="n">strucs</span> <span class="o">=</span> <span class="p">[</span><span class="n">group</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="k">for</span> <span class="n">group</span> <span class="ow">in</span> <span class="n">unique_strucs_grouped</span><span class="p">]</span>

            <span class="c1"># sort structures by objective function</span>
            <span class="n">strucs</span><span class="o">.</span><span class="n">sort</span><span class="p">(</span>
                <span class="n">key</span><span class="o">=</span><span class="k">lambda</span> <span class="n">x</span><span class="p">:</span> <span class="n">x</span><span class="o">.</span><span class="n">objective_function</span>
                <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">x</span><span class="o">.</span><span class="n">objective_function</span><span class="p">,</span> <span class="nb">float</span><span class="p">)</span>
                <span class="k">else</span> <span class="o">-</span><span class="n">np</span><span class="o">.</span><span class="n">inf</span>
            <span class="p">)</span>

            <span class="n">to_return</span> <span class="o">=</span> <span class="p">[</span>
                <span class="p">{</span><span class="s2">&quot;structure&quot;</span><span class="p">:</span> <span class="n">struc</span><span class="p">,</span> <span class="s2">&quot;objective_function&quot;</span><span class="p">:</span> <span class="n">struc</span><span class="o">.</span><span class="n">objective_function</span><span class="p">}</span>
                <span class="k">for</span> <span class="n">struc</span> <span class="ow">in</span> <span class="n">strucs</span>
            <span class="p">]</span>

            <span class="k">for</span> <span class="n">d</span> <span class="ow">in</span> <span class="n">to_return</span><span class="p">:</span>

                <span class="c1"># delete temporary objective_function attribute</span>
                <span class="k">del</span> <span class="n">d</span><span class="p">[</span><span class="s2">&quot;structure&quot;</span><span class="p">]</span><span class="o">.</span><span class="n">objective_function</span>

                <span class="c1"># reduce structure</span>
                <span class="k">if</span> <span class="n">reduction_algo</span><span class="p">:</span>
                    <span class="n">d</span><span class="p">[</span><span class="s2">&quot;structure&quot;</span><span class="p">]</span> <span class="o">=</span> <span class="n">d</span><span class="p">[</span><span class="s2">&quot;structure&quot;</span><span class="p">]</span><span class="o">.</span><span class="n">get_reduced_structure</span><span class="p">(</span>
                        <span class="n">reduction_algo</span><span class="o">=</span><span class="n">reduction_algo</span>
                    <span class="p">)</span>

            <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">return_ranked_list</span><span class="p">,</span> <span class="nb">int</span><span class="p">):</span>
                <span class="k">return</span> <span class="n">to_return</span><span class="p">[:</span><span class="n">return_ranked_list</span><span class="p">]</span>
            <span class="k">else</span><span class="p">:</span>
                <span class="k">return</span> <span class="n">to_return</span>

    <span class="nd">@property</span>
    <span class="k">def</span> <span class="nf">inverse</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;Returns: None&quot;&quot;&quot;</span>
        <span class="k">return</span> <span class="kc">None</span>

    <span class="nd">@property</span>
    <span class="k">def</span> <span class="nf">is_one_to_many</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;Returns: True&quot;&quot;&quot;</span>
        <span class="k">return</span> <span class="kc">True</span></div>


<div class="viewcode-block" id="MonteCarloRattleTransformation"><a class="viewcode-back" href="../../../pymatgen.transformations.advanced_transformations.html#pymatgen.transformations.advanced_transformations.MonteCarloRattleTransformation">[docs]</a><span class="k">class</span> <span class="nc">MonteCarloRattleTransformation</span><span class="p">(</span><span class="n">AbstractTransformation</span><span class="p">):</span>
    <span class="sa">r</span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    Uses a Monte Carlo rattle procedure to randomly perturb the sites in a</span>
<span class="sd">    structure.</span>

<span class="sd">    This class requires the hiPhive package to be installed.</span>

<span class="sd">    Rattling atom `i` is carried out as a Monte Carlo move that is accepted with</span>
<span class="sd">    a probability determined from the minimum interatomic distance</span>
<span class="sd">    :math:`d_{ij}`.  If :math:`\\min(d_{ij})` is smaller than :math:`d_{min}`</span>
<span class="sd">    the move is only accepted with a low probability.</span>

<span class="sd">    This process is repeated for each atom a number of times meaning</span>
<span class="sd">    the magnitude of the final displacements is not *directly*</span>
<span class="sd">    connected to `rattle_std`.</span>
<span class="sd">    &quot;&quot;&quot;</span>

    <span class="nd">@requires</span><span class="p">(</span><span class="n">hiphive</span><span class="p">,</span> <span class="s2">&quot;hiphive is required for MonteCarloRattleTransformation&quot;</span><span class="p">)</span>
    <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span>
        <span class="bp">self</span><span class="p">,</span>
        <span class="n">rattle_std</span><span class="p">:</span> <span class="nb">float</span><span class="p">,</span>
        <span class="n">min_distance</span><span class="p">:</span> <span class="nb">float</span><span class="p">,</span>
        <span class="n">seed</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">int</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span><span class="p">,</span>
        <span class="o">**</span><span class="n">kwargs</span>
    <span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Args:</span>
<span class="sd">            rattle_std: Rattle amplitude (standard deviation in normal</span>
<span class="sd">                distribution). Note: this value is not *directly* connected to the</span>
<span class="sd">                final average displacement for the structures</span>
<span class="sd">            min_distance: Interatomic distance used for computing the probability</span>
<span class="sd">                for each rattle move.</span>
<span class="sd">            seed: Seed for setting up NumPy random state from which random numbers</span>
<span class="sd">                are generated. If ``None``, a random seed will be generated</span>
<span class="sd">                (default). This option allows the output of this transformation</span>
<span class="sd">                to be deterministic.</span>
<span class="sd">            **kwargs: Additional keyword arguments to be passed to the hiPhive</span>
<span class="sd">                mc_rattle function.</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">rattle_std</span> <span class="o">=</span> <span class="n">rattle_std</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">min_distance</span> <span class="o">=</span> <span class="n">min_distance</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">seed</span> <span class="o">=</span> <span class="n">seed</span>

        <span class="k">if</span> <span class="ow">not</span> <span class="n">seed</span><span class="p">:</span>
            <span class="c1"># if seed is None, use a random RandomState seed but make sure</span>
            <span class="c1"># we store that the original seed was None</span>
            <span class="n">seed</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">random</span><span class="o">.</span><span class="n">randint</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">1000000000</span><span class="p">)</span>

        <span class="bp">self</span><span class="o">.</span><span class="n">random_state</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">random</span><span class="o">.</span><span class="n">RandomState</span><span class="p">(</span><span class="n">seed</span><span class="p">)</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">kwargs</span> <span class="o">=</span> <span class="n">kwargs</span>

<div class="viewcode-block" id="MonteCarloRattleTransformation.apply_transformation"><a class="viewcode-back" href="../../../pymatgen.transformations.advanced_transformations.html#pymatgen.transformations.advanced_transformations.MonteCarloRattleTransformation.apply_transformation">[docs]</a>    <span class="k">def</span> <span class="nf">apply_transformation</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">structure</span><span class="p">:</span> <span class="n">Structure</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">Structure</span><span class="p">:</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Apply the transformation.</span>

<span class="sd">        Args:</span>
<span class="sd">            structure: Input Structure</span>

<span class="sd">        Returns:</span>
<span class="sd">            Structure with sites perturbed.</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="kn">from</span> <span class="nn">hiphive.structure_generation.rattle</span> <span class="kn">import</span> <span class="p">(</span>  <span class="c1"># type: ignore</span>
            <span class="n">mc_rattle</span><span class="p">,</span>
        <span class="p">)</span>

        <span class="n">atoms</span> <span class="o">=</span> <span class="n">AseAtomsAdaptor</span><span class="o">.</span><span class="n">get_atoms</span><span class="p">(</span><span class="n">structure</span><span class="p">)</span>
        <span class="n">seed</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">random_state</span><span class="o">.</span><span class="n">randint</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">1000000000</span><span class="p">)</span>
        <span class="n">displacements</span> <span class="o">=</span> <span class="n">mc_rattle</span><span class="p">(</span>
            <span class="n">atoms</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">rattle_std</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">min_distance</span><span class="p">,</span> <span class="n">seed</span><span class="o">=</span><span class="n">seed</span><span class="p">,</span> <span class="o">**</span><span class="bp">self</span><span class="o">.</span><span class="n">kwargs</span>
        <span class="p">)</span>

        <span class="n">transformed_structure</span> <span class="o">=</span> <span class="n">Structure</span><span class="p">(</span>
            <span class="n">structure</span><span class="o">.</span><span class="n">lattice</span><span class="p">,</span>
            <span class="n">structure</span><span class="o">.</span><span class="n">species</span><span class="p">,</span>
            <span class="n">structure</span><span class="o">.</span><span class="n">cart_coords</span> <span class="o">+</span> <span class="n">displacements</span><span class="p">,</span>
            <span class="n">coords_are_cartesian</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span>
        <span class="p">)</span>

        <span class="k">return</span> <span class="n">transformed_structure</span></div>

    <span class="k">def</span> <span class="fm">__str__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="k">return</span> <span class="s2">&quot;</span><span class="si">{}</span><span class="s2"> : rattle_std = </span><span class="si">{}</span><span class="s2">&quot;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="vm">__name__</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">rattle_std</span><span class="p">)</span>

    <span class="k">def</span> <span class="fm">__repr__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="fm">__str__</span><span class="p">()</span>

    <span class="nd">@property</span>
    <span class="k">def</span> <span class="nf">inverse</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Returns: None</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="k">return</span> <span class="kc">None</span>

    <span class="nd">@property</span>
    <span class="k">def</span> <span class="nf">is_one_to_many</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Returns: False</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="k">return</span> <span class="kc">False</span></div>
</pre></div>

            <div class="clearer"></div>
          </div>
      </div>
      <div class="clearer"></div>
    </div>
    <div class="related" role="navigation" aria-label="related navigation">
      <h3>Navigation</h3>
      <ul>
        <li class="right" style="margin-right: 10px">
          <a href="../../../genindex.html" title="General Index"
             >index</a></li>
        <li class="right" >
          <a href="../../../py-modindex.html" title="Python Module Index"
             >modules</a> |</li>
        <li class="nav-item nav-item-0"><a href="../../../index.html">pymatgen 2020.7.3 documentation</a> &#187;</li>
          <li class="nav-item nav-item-1"><a href="../../index.html" >Module code</a> &#187;</li>
          <li class="nav-item nav-item-2"><a href="../../pymatgen.html" >pymatgen</a> &#187;</li>
        <li class="nav-item nav-item-this"><a href="">pymatgen.transformations.advanced_transformations</a></li> 
      </ul>
    </div>

    <div class="footer" role="contentinfo">
        &#169; Copyright 2011, Pymatgen Development Team.
      Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 3.1.2.
    </div>
<div class="footer">This page uses <a href="http://analytics.google.com/">
Google Analytics</a> to collect statistics. You can disable it by blocking
the JavaScript coming from www.google-analytics.com.
<script type="text/javascript">
  (function() {
    var ga = document.createElement('script');
    ga.src = ('https:' == document.location.protocol ?
              'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
    ga.setAttribute('async', 'true');
    document.documentElement.firstChild.appendChild(ga);
  })();
</script>
</div>

  </body>
</html>